I have a Polymer code which goes this way
<template>
<template repeat="{{item in tasklist}}">
<paper-checkbox <template if={{item.isDone}}>checked</template> label="{{item.itemName}}"></paper-checkbox>
</template>
</template>
What I am trying to do is based on the variable isDone whose value is boolean, I want to add checked attribute in paper-checkbox.
I am not sure if that is the correct way to do it.
The JSON object that I am using is as follows:
tasklist: [
{
itemName : "Study",
isDone : true
},
{
itemName : "Cook Dinner",
isDone : false
}
]
Can anyone give me the correct way to do it?
Thanks in advance.
First of all, the HTML must be still valid. You can’t simply drop tags inside other tags. Fortunately, in this case you don’t need to use conditional templates and the following code does the trick:
<paper-checkbox role="checkbox" checked="{{ item.isDone }}">
</paper-checkbox>
Whether you still want to use conditional template, you might write:
<template if="{{ item.isDone }}">
<paper-checkbox role="checkbox" checked>
</paper-checkbox>
</template>
<template if="{{ !item.isDone }}">
<paper-checkbox role="checkbox">
</paper-checkbox>
</template>
Live preview: http://plnkr.co/edit/V9ZukBq4ia2pqBk55DqH?p=preview
Hope it helps.
Related
I saw an example of linking directly to a form element using JsViews, which I found to be preferable to encapsulating the whole form in a template. Here is a jsfiddle example of what I'm trying to do, which partially works:
http://jsfiddle.net/30jpdnkt/
var app = {
selections: {
things: [
{ Name: "thingName1", Value: "thingValue1" },
{ Name: "thingName2", Value: "thingValue2" },
{ Name: "thingName3", Value: "thingValue3" }
]
},
formData: {
selectedThing: "thingValue1",
}
};
//how do I reference this template in-line, outside of another wrapping template?
$.templates({
theTmpl: "#theTmpl"
});
$("#content").link(true, app);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://www.jsviews.com/download/jsviews.js"></script>
<script id="theTmpl" type="text/x-jsrender">
<select id="thingChoice" data-link="formData.selectedThing">
<option value="-">Please select</option>
{^{for selections.things}}
<option data-link="value{:Value} {:Name} selected{:~selected === Value}"></option>
{{/for}}
</select>
</script>
<div id="content">
<!--this part works-->
<input data-link="formData.selectedThing trigger=true"/>
<!--this part does not display-->
<span {{for data tmpl="theTmpl"/}}></span>
</div>
The data-linked INPUT tag is correctly bound to the object, but I cannot find a working example of how to reference a compiled template in-line without encapsulating the entire form in another template. That it's possible to use data-link syntax outside of a template gives hope that it may be possible with correct syntax.
Is this possible?
Yes it is possible - it is what I call top-level data-linking. There will be new documentation topics on this coming very soon, but meantime you have this sample:
http://www.jsviews.com/#samples/editable/toplevel-for
And your jsfiddle - which I updated to make it work fully: http://jsfiddle.net/30jpdnkt/1/
<div id="content">
<input data-link="formData.selectedThing trigger=true"/>
<span data-link='{for tmpl="theTmpl"}'></span>
</div>
So I'm looking for some understanding on how templates and such work.
I've movie.html file with a template named movies in it, with a movie.js helper that returns a collection.
Movies Template
<template name="movies">
<li>{{title}}</li>
</template>
JS Helpers
Template.body.helpers({
movie: function () {
return Movies.find({});
}
});
Now I've another template that does a bunch of other things but one of them is to iterate over this list and display it.
List Template
<template name="list">
<ul>
{{#each movie}}
{{> movies}}
{{/each}}
</ul>
</template>
In this situation the list doesn't popular with the data.
However, if I move the contents of the list template outside of a template and just on the main.html it works great!
This is how I used to use it but I've started to use Houston Admin Package which uses Iron:Router so I've moved the main (and only) page to a template for routing purposes, which breaks my looping list.
I'm sure I'm missing something minor but I can't figure it out.
You are using the {{#each movie}} helper on the list Template so change the Template.helper to the list template
Template.list.helpers({
movie: function () {
return Movies.find({});
}
});
We are you calling this <template name="list"> on the body tag? you have something like this.
<body>
{{> list}}
</body>
Or you have something like this.
<template name="layout">
{{> yield}} <!-- since you are mentioning iron:route package -->
</template>
Or you have a route to that list template? localhost:3000/lists
Router.route('/movie-lists', function () {
this.render('lists')
});
On whatever of this 3 cases, you should point the helper into the template where you are calling it (in this case list template)
Is it possible to have an if / else statement which does not render any html in a view similar to knockout:
<!-- ko if: someExpressionGoesHere -->
but it needs to be on an element
Yes, but if v-if conditional is false, it's not added to DOM tree.
HTML
<div id="main"></div>
JavaScript
new Vue({
el: "#main",
template: '<div v-if="name"><span v-text="name"></span></div>',
data: {
// name: "bob"
}
});
console.log(document.body.innerHTML);
// <div id="main"><!--vue-if--></div>
Still not good for you?
I know the question was already answered, but thought I would pass along something I use, now that I am writing sites with Vue (which I love.) I am a fan of Knockout and have many sites written in it using the:
<!-- ko if: someExpressionGoesHere -->
You could do a similar thing in Vue like this:
<template v-if="someExpressionGoesHere">
<p>Expression is True</p>
</template>
<template v-else>
<p>Expression is False</p>
</template>
The templates will not render anything to the page. The resulting html will be a single p of the 'Expression is xxx'.
I think it is a bit more clear of what the intent of the code is here than the actual answer to this post IMHO.
you can also use this way to write if else condition in vue.js
<template>
<div id="app">
<p v-if="someConditionHere">Condition True</p>
<p v-else>Condition False</p>
</div>
</template>
I'm trying to add an attribute to many external links. The below code worked prior to Blaze, which only runs Template.rendered once now (but the below code doesn't run as desired one time even).
So what is an alternative way to add an attribute to many links once the page has been rendered or what is the correct way to do this with Meteor now? BTW, I researched quite a few things, including this example app from the author, which if it has the answer, I didn't see it.
Template.layout.rendered = function () {
console.log('CALLED'); // runs
$(document).ready(function () {
console.log('NOW THIS'); // runs
$('a.external').each(function () {
console.log('NOT CALLED'); // doesn't run
$(this).attr('target', '_blank');
});
});
};
There are several ways to deal with this problem, none of them is perfect. It's worth noting that this issue has been raised and most likely it will be solved via a custom event as proposed here.
For now, the simplest way to do this is to move each element you need to adjust to a separate template. So instead of:
<template name="layout">
{{#each links}}
<a class="external" ...>
{{/each}}
</template>
You will have:
<template name="layout">
{{#each links}}
{{> layout_externalLink}}
{{/each}}
</template>
<template name="layout_externalLink">
<a class="external" ...>
</template>
I'm having trouble understanding exactly what is available as my context in a template invoked by Meteor with Iron-Router – and how these things inherit.
Here are all the potential sources for "stuff I can refer to inside double curly braces" that I can think of:
Built-in helpers
Handlebars.registerHelper(...)
Template.myTemplate.myVar/myHelper = ...
Template.myTemplate.helpers({ ... })
data: { ... } inside route (Router.map)
Something to do with #each?
Something to do with #with?
Have I forgotten anything? Are there any global variables?
I guess I'm a bit confused about what the standard way is of giving the template a context in the first place. Also about what happens inside control structures such as #each and #with.
A clarification would be great!
IronRouter renders your template with the result of RouteController.data as the current data context.
<template name="viewPost">
<div>
<h1>{{title}}</h1>
<p>{{content}}</p>
</div>
</template>
var PostsController=RouteController.extend({
template:"viewPost",
waitOn:function(){
return Meteor.subscribe("postsById",this.params._id);
},
data:function(){
return Posts.findOne(this.params._id);
}
});
this.route("viewPost",{
path:"/posts/:_id",
controller:PostsController
});
In this example, IronRouter will render the "viewPost" template with the post having this.params._id as data context.
What is the standard way of giving a template a context in the first place ?
There is 2 ways :
{{#with myContext}}
{{> myTemplate}}
{{/with}}
{{> myTemplate myContext}}
As you can see, the #with control structure sets the current data context.
The #each structure iterates over a Cursor (or an Array) and sets the current data context to the current fetched document (or the current cell).
<template name="postsList">
{{#each posts}}
<h1>{{title}}</h1>
{{/each}}
</template>
Template.postsList.helpers({
posts:function(){
// cursor
return Posts.find();
// array
return [{title:"Title 1"},{title:"Title 2"},{title:"Title 3"}];
}
});
UPDATE : Could you possibly add a note about inheritance ? For instance, if I have nested #each blocks, do variables cascade ?
I came up with this example :
<template name="parent">
<ul>
{{#each parentContexts}}
{{> child}}
{{/each}}
</ul>
</template>
<template name="child">
<li>
<ul>
{{#each childContexts}}
{{> content}}
<p>../this.parentProperty = {{../this.parentProperty}}</p>
{{/each}}
</ul>
</li>
</template>
<template name="content">
<li>
<p>this.childProperty = {{this.childProperty}}</p>
<p>this.parentProperty = {{this.parentProperty}}</p>
</li>
</template>
Template.parent.helpers({
parentContexts:function(){
return [{
parentProperty:"parent 1"
},{
parentProperty:"parent 2"
}];
}
});
Template.child.helpers({
childContexts:function(){
return [{
childProperty:"child 1"
},{
childProperty:"child 2"
}];
}
});
If you run this example, you'll notice that you can't access the parentProperty in "content" because the default #each helper OVERRIDES the parent data context with the new context provided.
You can access the parentProperty in the nested #each block using this syntax : ../this.parentProperty, which is reminiscent of the UNIX parent directory access syntax.
However you cannot use this syntax in the "content" template, because it is agnostic of the nested each structures it was called from : you can only use the ../../parent syntax in a template where the actual nesting happens.
If we want to access the parentPropery in the content template, we must augment the current data context with the parent context.
To do so, we can register a new #eachWithParent helper like this :
Handlebars.registerHelper("eachWithParent",function(context,options){
var parentContext=this;
var contents="";
_.each(context,function(item){
var augmentedContext=_.extend(item,parentContext);
contents+=options.fn(augmentedContext);
});
return contents;
});
Now if you replace the nested #each with this new helper, you will have access to parentProperty in "content".