Handlebars escape current context - handlebars.js

I have a web component in my handlebar template that has its own context e.g., this object person{name: "singh"} only exists within <mycompnent></mycomponent>.
I use \{{person.name}} to escape the default handlebar root context and use the local context inside the web component. This works <mycompnent>\{{person.name}}</mycomponent>.
However, I am not able to determine how to use this inside an if expression. My attempts like below all are resulting in error.
<mycompnent>{{#if \person.name }}<p>Good</p>{{/if}}</mycompnent>
<mycompnent>{{#if (\person.name) }}<p>Good</p>{{/if}}</mycompnent>
<mycompnent>{{#if \(person.name) }}<p>Good</p>{{/if}}</mycompnent>
Full code block
<!-- This prints the root -->
{{JSONstringify #root}}
<ul>
{{#each #root.data.items as |item|}}
<li>
<!-- mycomponent exposes a object named person inside the template-->
<mycomponent id="{{item.ID}}">
<template>
<!-- This prints out the item object -->
{{JSONstringify .}}
<!-- This prints out the person object -->
\{{person}}
<!-- This print out the person name if it is set -->
<p>\{{person.displayName}}</p>
<!-- This results in error -->
{{#if (\person.displayName) }}<p>\{{person.displayName}}</p>{{/if}}
</template>
</mycomponent>
</li>
{{/each}}
</ul>

Related

Adding a css class in a dynamically created handlebars template

I have a JSON object that I am looping through to dynamically create x amount of ULs then LIs. I need to create two {{#each}} to create the content. However when I add a CSS class to my handlebars template it does not come through onto the UL as it does in the second {{#each}} - how do I stop this? Here is the template:
<div class="{{panel-container__Css-class}} {{panel-menu__Css-class}}" data-component="panel">
{{#each sections}}
<ul id="{{id}}" class="{{panel-menu__Css-class}}">
{{#each list}}
<li>{{title}}</li>
{{/each}}
</ul>
{{/each}}
</div>
Here is what i am passing in:
<nav data-component="navigation">
{{> nav-dropdown menu-button__Css-class="menu-button" menu-button__Css-class-nav="panel" target-id="panel-nav" }}
{{> nav-dropdown menu-button__Css-class="region-button" menu-button__Css-class-nav="region" target-id="panel-region" menu-button__copy=panel.copy}}
{{!--var links = [{"title": "Test","url": "/"}];--}}
{{> panel panel-menu__Css-class="navigation__menu-styles" panel-container__Css-class="navigation__menu-container" sections=navigation.sections links=navigation.sections.list }}
</nav>
I think what you are looking for is the Handlebars path that will allow you to obtain the value of panel-menu__Css-class from within {{#each sections}}. You need to understand that when you are within {{#each sections}}, your this context is the currently iterated element of the sections array. You must step up a level to the parent context which has the panel-menu__Css-class property you are trying to access:
<ul id="{{id}}" class="{{../panel-menu__Css-class}}">

Inject data into scope without <template>

I would like to get rid of two lines in the html used in a vue 2.x application. The lines with <template scope="props"> and the corresponding </template> should not be necessary.
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<p>{{ message }}</p>
<my-component>
<template scope="props">
<p>{{props.test}}</p>
</template>
</my-component>
</div>
I would rather define my own component attribute to define the scope name
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<p>{{ message }}</p>
<my-component with="props">
<p>{{props.test}}</p>
</my-component>
</div>
So instead of exposing the writer of the HTML to the concepts of templates and scopes we would do that inside my-component.
Does anybody know whether the vue templating mechanism is open for extension inside components like this ?
The benefit of having component is that it can be re-used at multiple places. so idea is to define template at one place and you can use it at multiple places.
the example you have written, you will be able to re-use it at again. template of component is generally not defined inside component, it will be separate and than that component can be used at multiple places.
See one sample below:
<div id="app">
<template id="item-edit">
<li>
<span v-show="!inEdit">{{item.name}}</span>
<input v-show="inEdit" type="text" v-model="item.name" />
{{inEdit ? 'save' : 'edit'}}
</li>
</template>
<ul>
<item-edit v-for="item in items" :item="item"></item-edit>
</ul>
</div>
Complete fiddle: http://jsfiddle.net/corh2tqo/

Data binding in polymer content tag

I am new to polymer & trying to create a configurable template for the received iron-ajax response, means the end user who is using the component can decide the items which need to be displayed in the screen, so I used content tag inside the template but the data is not getting bind with my custom element.
index.html
<custom-element>
<div class="selected_content">
<h2>{{item.id}}</h2>
<span>{{item.member.dept.name}}</span>
</div>
</custom-element>
customElement.html
<iron-ajax
auto
url={{url}}
handle-as="json"
last-response={{lastresponse}}
debounce-duration="300"></iron-ajax>
<template is="dom-repeat" items=[[lastresponse]]>
<content select=".selected_content"></content>
</template>

Data available ("this") from a template event handler

projects.html
{{#if projects}}
{{#each projects}}
<div class="project-item">
<div class="project-name">
{{name}}
</div>
<div class="project-settings">
<span class="rename">Rename</span>
<span class="edit">Edit</span>
<span class="delete">
<!-- Here -->
</span>
</div>
</div>
{{/each}}
{{/if}}
projects.js
Template.Projects.events({
"click .project-item .delete": function (e, template) {
e.preventDefault();
debugger
// "this" refers to the specific project
}
});
In an event handler, I noticed "this" conveniently refers to a specific object inside the template where the event is related to. For example, in this case, the delete button is inside each projects block, and the handler for the delete button has this = some project. This is convenient, but I'd like to know the scopes and rules more completely. Can someone explain in briefly and point me to the right document?
This is a data context sensitive feature. Basically, there is a lexical scope in spacebars helpers. Have a look at this: http://devblog.me/no-data-context.html
The original pull request is here: https://github.com/meteor/meteor/pull/3560

How do i get an onload function on the body for a specific template using meteor.js?

I'm trying to get the following behavior for a certain template:
<body onload="someInitFunction();">
Let's say i have the following markup (i'm using mrt router, not iron-router, for {{renderPage}}):
// Main Template
<head>
<title>meteorite-knowviz</title>
</head>
<body>
{{> header}}
<div class="container-fluid">
<div class="row">
{{renderPage}}
</div>
</div>
{{> footer}}
</body>
That renderPage is the secondTemplate:
<template name="secondTemplate">
{{#if currentUser}}
<div class="col-md-2">
<div class="list-group">
<a class="list-group-item" href="{{render thirdTemplate please...}}">Third Template</a>
<a class="list-group-item" href="{{render fourthTemplate please...}}">Fourth Template</a>
</div>
</div>
// In this case let's say thirdTemplate gets rendered
{{render the choice taken above please...}}
{{/if}}
</template>
And within this template, depending on which link was clicked on, (in this case the third) there will finally be a thirdTemplate, which will show a data visualization with some help by a javascript framework, which will be in need of a <body onload="initFunction();">in order to display the data:
<template name="thirdTemplate">
<div class="col-md-5">
<h2>THIS!! section needs a "<body onload="initFunction();"> in order to work" ></h2>
</div>
<div class="col-sm-5">
<h2>Some other related content here</h2>
</div>
</template>
To sum up i have three questions:
1a. How could i get the third template to get a <body onload="initFunction();">
2a. In which way can i render different templates within the secondTemplate?
2b. Can i use a {{renderPage}} within this template even though this template is the renderedPage in the main template or should i do it in some other way?
In order to get the <body onload="initFunction();"> i had to do the following:
First add the following function to a .js file in the client folder:
Template.thirdTemplate.rendered = function() { // Template.thirdTemplate.created - also worked.
$('body').attr({
onload: 'init();'
});
}
This however got me an error saying that initFunction is not defined. In an standard html page my could work just fine, but in meteor i had to change my function from:
function initFunction(){
//what ever i wished to do
}
To:
init = function() {
//what ever i wished to do
}
Regarding the rendering of pages, iron-routing is the way to go since the router add on is not under development any more.
1a. How could i get the third template to get a <body
onload="initFunction();">
You probably want to call initFunction when the third template has been rendered, so just put your call to it in the rendered callback.
Template['thirsTemplate'].rendered = function(){
initFunction()
}
2a. In which way can i render different templates within the
secondTemplate?
2b. Can i use a {{renderPage}} within this template even though this
template is the renderedPage in the main template or should i do it in
some other way?
Listen for clicks on the links, and when one happen you manually render the desired template (possible with Meteor.render, if you need reactivity) and add it to the right node in the document. See this question.
It may be possibly to achieve with router (I don't know that package).
I think that what you want to use is the created callback, that will be called each time your template is created, and not the rendered callback, that would be called each time a change has caused the template to re-render.
Template.thirdTemplate.created = function(){
initFunction()
}
See the documentation for templates for other types of callbacks: http://docs.meteor.com/#templates_api

Resources