I've created view App.TestView which works fine outside following each loop. The code is displaying properly test loop_element.
App.TestView = Ember.View.extend({});
{{#view App.TestView}}
test
{{/view}}
{{#each controller.positions itemController='url'}}
loop_element
{{/each}}
On the other hand, when I put child view inside each loop
{{#each controller.positions itemController='url'}}
loop_element
{{#view App.TestView}}
test
{{/view}}
{{/each}}
is not displaying anything. There isn't any error message. What can be wrong? Why can't I use views inside loop?
It looks like it's working to me. Are you sure you're looping the same thing? You wrote two different items that you were iterating. controller.positions is probably empty
App.TestView = Em.View.extend({
});
App.UrlController = Em.ObjectController.extend({
});
<script type="text/x-handlebars" data-template-name="index">
{{#each controller.positions itemController='url'}}
loop_element
{{#view App.TestView}}
test2
{{/view}}
{{/each}}
</script>
http://emberjs.jsbin.com/bapugowi/1/edit
The thing was that the loop was inside <tbody> tag. View was rendered in other tag than <tr> and it was breaking my web browser.
Related
I have a problem with a linkTo that points to itself. The actual problem is in an application that has a sidebar with a set of links. The first time a click the link the model and view is loaded and displayed properly. However on the second click the view and/or model disappear.
I've condensed the problem in this jsfiddle. The index route displays a list of links and when clicking on one of the links it will display the detail. In the detail page I have a link to itself but when I click it the model does not show.
The detail template shows the content fine but note the {{firstName}} or {{lastName}}
<script type="text/x-handlebars" data-template-name="item">
<h2>Item Content:</h2>
{{#linkTo "item" id}}Reload me{{/linkTo}}
{{content}}
<ul>
<li>{{firstName}} {{lastName}}</li>
</ul>
</script>
I think the issue is similar to Ember.js - linkTo error on second call
Updated sample
Here is a new example With linkTo at the top levelwhere the {{linkTo}} item is in the top level application template
<script type="text/x-handlebars" data-template-name="application">
{{#linkTo "test" 0}}Test 0{{/linkTo}}
{{outlet}}
</script>
Following #intuitivepixel solution using an action gives me the same result
<script type="text/x-handlebars" data-template-name="application">
<a href="#" {{action reloadMe "test" 0}}>Test 0</a>
{{outlet}}
</script>
Not everything can be done with the {{linkTo}} helper, IMO for this kind of feature (like a reload) you should go for a {{action}} helper instead.
First define the action that does the routing for you when called:
App.TestRoute = Ember.Route.extend({
events: {
reloadMe: function(route, content) {
this.transitionTo(route, content);
}
},
serialize: function(model) {
return {id: model.id};
}
});
And then in your template:
<a href="#" {{action reloadMe "test" content}}>Reload me</a>
See here how you could implement it: http://jsfiddle.net/FSd6H/4/
Hope it helps.
I have a controller with data about user accounts (icon, name, provider, etc.). Within the output of the each loop I have a view that will build a CSS class dynamically based on the provider passed in via that specific model.
<script type="text/x-handlebars" data-template-name="accountItem">
{{#each account in controller}}
{{#view App.AccountView}}
<h4>{{account.name}}</h3>
<img {{bindAttr src="account.icon"}} />
<i {{bindAttr class="account.provider"}}></i>
{{/view}}
{{/each}}
</script>
App.AccountView = Ember.View.extend({
tagName: 'a',
classNames: ['avatar-image'],
providerClass: function(el) {
// do something
}
});
The question I have is two-fold.
How do you pass in "account", or the currently iterated item, into the view?
After you pass it in, how do you reference it?
I'm sure this is something that happens quite often but I can't seem to find any examples. Can anyone offer some input on this please?
Views has a special content property in a view which allows a more simple approach: you just use a name of the model's property without the view.content. part.
Also, when you're iterating over controller, you can omit the name of loop variable and use this instead, like in this guide. This is not necessary but can make the code a bit cleaner.
Also, from within view's template you generally don't need to reference the outside variables although you can if you like..
{{#each controller}}
{{#view App.IndexView contentBinding="this"}}
<h4>{{name}}</h4>
<img {{bindAttr src="icon"}} />
<i {{bindAttr class="provider"}}></i>
<i> {{icon}} </i>
<i>{{provider}}</i>
{{/view}}
{{/each}}
And you can always access the content property from within the view with:
this.get('content');
The currently iterated item can be passed into the view with the help of property bindings and it can be refered as "{{view.property}}" in the template. For example:
{{#each account in controller}}
{{#view App.IndexView itemBinding="account"}}
<h4>{{view.item.name}}</h3>
<img {{bindAttr src="account.icon"}} />
<i {{bindAttr class="account.provider"}}></i>
<i> {{view.item.icon}} </i>
<i>{{view.item.provider}}</i>
{{/view}}
{{/each}}
I have created a simple jsfiddle for the above case. Do check it and let me know if you were able to resolve the issues.
Fiddle url : http://jsfiddle.net/nCyn6/3/
I'm trying to use the Bootstap.Tabs component to create some bootstrap tabs.
I've declared the tabs as follows:
{{view Bootstrap.Tabs
contentBinding="App.tabsContent"
selectionBinding="App.selection"}}
And I'm using the following code to set up the content for the tabs.
App.ready = function() {
App.tabsContent= Ember.A([{value: "cred_app.associate_clients", title: "Associate clients"}, {value: "cred_app.facilities", title: "Facilities"}]);
};
Using this I can successfully render the bootstrap tabs.. and the route name pops up in App.selection.
I just don't understand how to get the links working, so that controller will transition to the route. I'd also like to get the active tab get the correct css applied to it so that the tabs show which route is currently being displayed.
UPDATE:
I have implemented this using a more simplistic approach:
<ul class='nav-tabs'>
{{#linkTo 'cred_app.associate_clients' model tagName='li' href=false}}
{{#linkTo 'cred_app.associate_clients' model}}Client Hierachy{{/linkTo}}
{{/linkTo}}
</ul>
You can do something like this:
(using my derived Bootstrap.Tabs implementation)
{{#view Bootstrap.TabContainerView currentView="patient"}}
<ul class="nav nav-tabs">
{{#view Bootstrap.TabView value="patient"}}<a>Patient</a>{{/view}}
{{#view Bootstrap.TabView value="visits"}}<a>Visits</a>{{/view}}
{{#view Bootstrap.TabView value="contacts"}}<a>Contacts</a>{{/view}}
{{#view Bootstrap.TabView value="sessions"}}<a>Sessions</a>{{/view}}
</ul>
{{#view Bootstrap.TabPaneView viewName="patient"}}
{{render "patient"}}
{{/view}}
{{#view Bootstrap.TabPaneView viewName="visits"}}
{{render "visits"}}
{{/view}}
{{#view Bootstrap.TabPaneView viewName="contacts"}}
{{render "contacts"}}
{{/view}}
{{#view Bootstrap.TabPaneView viewName="sessions"}}
{{render "sessions"}}
{{/view}}
{{/view}}
or using the router:
<ul class="nav nav-tabs">
{{#view Bootstrap.TabItem item="patient"}}
{{#linkTo "tab.patient" content}}Patient{{/linkTo}}
{{/view}}
{{#view Bootstrap.TabItem item="visits"}}
{{#linkTo "tab.visits" content}}Visits{{/linkTo}}
{{/view}}
{{#view Bootstrap.TabItem item="contacts"}}
{{#linkTo "tab.contacts" content}}Contacts{{/linkTo}}
{{/view}}
{{#view Bootstrap.TabItem item="sessions"}}
{{#linkTo "tab.sessions" content}}Sessions{{/linkTo}}
{{/view}}
</ul>
{{outlet}}
the magic is done by the Bootstrap.TabItem, it gets the active state from the linkTo helper
Bootstrap.TabItem = Ember.View.extend({
tagName: 'li',
classNameBindings: ['active'],
activeChanged: function () {
var self = this;
Ember.run.next(this, function () { //delay
if (!self.isDestroyed) {
self.set('active', self.get('childViews.firstObject.active'));
}
});
}.observes('childViews.firstObject.active') //get the active state from the linkTo helper
});
now you only need a router, something like this:
App.Router.map(function (match) {
...
this.resource('tab', { path: '/tab' }, function () {
this.route('patient');
this.route('visits');
this.route('contacts');
this.route('sessions');
});
...
});
a jsFiddle might help
Please look at Bootstrap for Ember
It fully supports Pills & Tabs:
https://github.com/ember-addons/bootstrap-for-ember
Showcase: ember-addons.github.io/bootstrap-for-ember
Though the "posts/index" template is rendering, the emberjs #each helper inside the template does not produce any output. this is the jsfiddle: http://jsfiddle.net/rxWzu/
I have tried this:
{{#each post in content}}
<p> {{post.title}} </p>
<p>{{#linkTo 'posts.post' post}} {{post.body}} {{/linkTo}}</p>
{{/each}}
and this
{{#each controller}}
<p>{{title}} </p>
<p>{{#linkTo 'posts.post' post}} {{body}} {{/linkTo}}</p>
{{/each}}
Thanks.
You should use EmBlog.Post.find() in your model method for EmBlog.PostsIndexRoute.
EmBlog.PostsIndexRoute = Ember.Route.extend({
model: function(){
return EmBlog.Post.find();
}
...
Also, you don't need to call setupController in either of your routes. The way you called it is the default in Ember.
JSFiddle example
Controller:
games : Ember.A(["1", "2", "3"]),
View:
{{#each view.games}}
{{view Ember.TextField valueBinding="this"}}
{{/each}}
when I change the value of the textfield, it didn't change the array at the same time?
Hum, I feel weird on this... If you use objects in the array, then the bindings works well, with strings, as you do, effectively it's not working...
<script type="text/x-handlebars">
<h5> work with object </h5>
{{#each plop in App.controller1}}
{{view Em.TextField valueBinding="plop.name"}} {{plop.name}}
{{/each}}
<h5> don't work with strings </h5>
{{#each plop in App.controller2}}
{{view Em.TextField valueBinding="plop"}} {{plop}}
{{/each}}
</script>
window.App = Ember.Application.create({
controller1: Ember.ArrayController.create({
content: [{name:"aaaa"}, {name:"bbbbb"}, {name:"ccccc"}]
}),
controller2: ["aaaa", "bbbbb", "cccc"]
});
http://jsfiddle.net/Sly7/SQ5g8/
EDIT: Thanks to Kris Selden, who explains me that is intented behavior, since two ways bindings work through obj[key], obviously, a string has no such key. And to conclude, there is no binding based on array position.