Embers View - loose content - ember.js

I have a rails app with ember that render one template where i want to render the app´s notes list.
The main template is :
<div class="container" style="margin-top: 30px">
......
<ul class="nav nav-list">
<li class="nav-header">list notes</li>
#ERROR -> {{ view App.NotesListView contentBinding='App.NotesIndexController' }}
</ul>
</div>
{{#linkTo "notes.new"}} <button class="btn btn-primary">Add Note</button>{{/linkTo}}
</div>
......
</div>
</div>
I have the notes_index_controller:
App.NotesIndexController = Em.ArrayController.extend
init: ->
console.log "entra en notes index controller"
selectedResource: null
isEmpty:( ->
#get('length') == 0
).property('length')
and the index_route :
App.NotesIndexRoute = Em.Route.extend
model: ->
App.Note.find()
setupController:(controller, model ) ->
controller.set('content', model )
controller.set('users', App.User.find() )
When i try to render this view ( App.NotesListView ) :
App.NotesListView = Ember.View.extend
templateName: "notes/list"
list.hbs
{{#each content}} #I supose that have to be the NotesIndex´s content but not it is
<li>test</li>
<li>{{ view App.NoteListItemView contentBinding='this' }}</li>
{{/each}}
I cann´t bind the NotesIndexController ( where i get the list of notes ) with the content of this view.
What is the correct way to do this ?

Assuming your main template is index you should be able to access your App.NotesIndexController content by requiring the nodesIndex controller with the needs API in your IndexController:
JS
App.IndexController = Em.ArrayController.extend
content: []
needs: ['notesIndex']
notesBinding: 'controllers.notesIndex.content'
Handlebars
<script type="text/x-handlebars" id="index">
...
{{view App.NotesListView contentBinding='notes'}}
...
</script>
If your main template is application you should be able to do the same but requiring your notesIndex controller on the ApplicationController instead:
JS
App.ApplicationController = Em.ArrayController.extend
content: []
needs: ['notesIndex']
notesBinding: 'controllers.notesIndex.content'
Handlebars
<script type="text/x-handlebars" id="application">
...
{{view App.NotesListView contentBinding='notes'}}
...
</script>
Edit in response to your last comment:
try rewrite the setupController hook in you NotesIndexRoute to this:
...
setupController:(controller, model) ->
#_super(controller, model)
controller.set('users', App.User.find())
...
Hope it helps.

Related

Nothing rendered into outlet

I am manually rendering some outlets:
Dashboard.IndexRoute = Ember.Route.extend({
renderTemplate : function ( ) {
this.render('index');
this.render('disposition-legend', {outlet : 'dispositionLegend'} );
},
});
The templates:
<script type="text/x-handlebars" data-template-name="application">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
<div class="container">
{{outlet dispositionLegend}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="disposition-legend">
<div class="row">
<div class="col-lg-12 well">Legend:
{{#each controller.content}}
<span class="label" style="background-color:{{unbound color}};">{{label}}</span>
{{/each}}
</div>
</div>
</script>
Ember says that is is indeed rendering the outlet:
Rendering index with default view <Ember._MetamorphView:ember320> Object {fullName: "view:index"}
Rendering disposition-legend with <Dashboard.DispositionLegendView:ember328> Object {fullName: "view:disposition-legend"}
There are no error messages, but neither view ember320 nor view ember328 are in the DOM. The only view present in the DOM is ember299, related to the application template.
Why could that be?
(I am running ember-1.4.0)
The IndexRoute is trying to render into application template, but you want to render into index, so you need to pass the into: 'index' option.
App.IndexRoute = Ember.Route.extend({
renderTemplate : function ( ) {
this.render('index');
this.render('disposition-legend', {outlet : 'dispositionLegend', into: 'index'} );
},
});

Change a view property from an unrelated controller

I have the following view:
App.MessageTrayView = Bootstrap.AlertMessage.extend({
message: 'This is a message.',
});
Displayed in this template:
<script type="text/x-handlebars" data-template-name="nodes">
<article>
<form class="form-horizontal">
<fieldset>
{{view App.MessageTrayView id="message-tray-view"}}
<div id="legend" class="">
<legend class="">Nodes <span class="badge">{{controllers.nodesIndex.length}} records</span>
<div class="pull-right">
<a {{action destroyAllRecords}}><i class="icon-remove-circle"></i><a/>
{{#linkTo "nodes.new" class="btn btn-primary"}}Add Node{{/linkTo}}
</div>
</legend>
</div>
{{outlet}}
</fieldset>
</form>
</article>
</script>
And this unrelated controller:
App.NodesIndexController = Ember.ArrayController.extend({
destroyAllRecords: function () {
console.log('destroyAllRecords called');
App.MessageTrayView.set('message', 'All nodes have been deleted');
},
});
I want to change the message displayed as soon as the destroyAllRecords is triggered. This is not working (the error message in the console is telling me that I am doing something * very* wrong). How can I change the message property, so that the changes are directly visible on the page?
You can see the code live here
One quick way of doing this could be to define a property on the App namespace:
App = Ember.Application.create({
messageTrayContent: ''
});
then bind to it in your view using the suffix Binding after your property name:
App.MessageTrayView = Bootstrap.AlertMessage.extend({
messageBinding: 'App.messageTrayContent'
});
Now doing:
App.NodesIndexController = Ember.ArrayController.extend({
destroyAllRecords: function () {
console.log('destroyAllRecords called');
App.set('messageTrayContent', 'All nodes have been deleted');
},
});
should work.
Hope it helps.

How do I pass model information to this each statement in a nested template?

I have an index route where I need to populate a menu in one outlet based on a list of models. However I cannot get the models to be represented in the each statement.
Here is the Category Model:
App.Category = DS.Model.extend({
title: DS.attr('string'),
parent: DS.belongsTo('App.Category')
})
And here is the indexRoute where I render it
App.IndexRoute = Em.Route.extend({
renderTemplate: function(){
this.render('index')
this.render('categoryMenu',
{
outlet: 'sidebar',
into: 'index',
model: function() {
return App.Category.find()
},
controller: App.CategoriesController
})
this.render('badgesList',{
outlet: 'badgesList',
into: 'index'
})
}
})
Index Template:
<script type="text/x-handlebars" data-template-name="index">
<div class="span3">
{{outlet sidebar}}
</div>
<div class="span8">
{{outlet badgesList}}
</div>
</script>
Nested Category Template
<script type="text/x-handlebars" data-template-name="categoryMenu">
<ul>
{{#each model}}
{{title}}
{{/each}}
</ul>
</script>
I have tried to change the each statement to several different things like controller or item in model but nothing is displayed.
Thank you for any help!
Make yourself CategoriesController first like this:
App.CategoriesController = Ember.ArrayController.extend({
content: function () {
return App.Category.find()
}.property()
});
rename your template just to categories
<script type="text/x-handlebars" data-template-name="categories">
<ul>
{{#each model}}
{{title}}
{{/each}}
</ul>
</script>
in your index template replace {{outlet}} with {{render 'categoies'}}
<script type="text/x-handlebars" data-template-name="index">
<div class="span3">
{{render 'categoies'}}
</div>
<div class="span8">
{{outlet badgesList}}
</div>
</script>
as last thing remove the call rendering categoryMenu.

Ember.js template rendering

I'm possibly reading the docs wrong. Can someone please check out my gist and tell me why the invoices/index template is not rendering?
When I read the ember.js docs it states it should render
posts
↳posts/index
(invoices/index in my case). The invoices template renders however.
Handlebars:
<script type="text/x-handlebars" data-template-name="application">
<h1>Ember Committers</h1>
<nav>
{{#linkTo "index"}}Index{{/linkTo}}
{{#linkTo "about"}}About{{/linkTo}}
{{#linkTo "invoices"}}Invoices{{/linkTo}}
</nav>
{{ outlet }}
</script>
<script type="text/x-handlebars" data-template-name="invoices">
<h1>Invoices</h1>
</script>
<script type="text/x-handlebars" data-template-name="invoices/index">
<ul>
{{#each invoice in invoices }}
<li>{{#linkTo "show" invoice.id}}{{ invoice.id }}{{/linkTo }}</li>
{{/each }}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="invoices/show">
<p>Invoice - {{ name }}</p>
</script>
<script type="text/x-handlebars" data-template-name="phone">
<p>Contributor - {{ title }}</p>
</script>
<script type="text/x-handlebars" data-template-name="about">
<p>About {{ title }}</p>
</script>
<script type="text/x-handlebars" data-template-name="index">
<p>Index</p>
</script>
JavaScript:
<script type="text/javascript" defer>
var App = Ember.Application.create({
LOG_TRANSITIONS: true
});
App.ApplicationView = Ember.View.extend({
templateName: 'application'
});
App.Router.map(function () {
this.route("about");
this.resource("invoices", { path: "/invoices" }, function () {
this.resource("show", { path: "/:id" });
});
});
var invoices = [
{id: 1},
{id: 2}
];
App.AboutRoute = Ember.Route.extend({
setupController: function (controller) {
// Set the IndexController's `title`
controller.set('title', "My App");
}
});
App.InvoicesIndexController = Ember.ArrayController.extend({
invoices: invoices
});
</script>
You need to include an {{outlet}} tag in your invoices template. Since index and show are nested resources of invoices, their templates get rendered inside the outlet that you specify in the invoices template.
Take a look at the nested resources part of the Ember.js guide.

Emberjs rendering wrong template

I am working with EmberJs and can't figure out why the following code won't render the 'new' template. When I navigate to /shops, I get a list of shops and a create button linking to '/shops/new', but when I click create, the 'new' template isn't rendered and instead stays the same as 'shops'. I can navigate to each individual shop fine, just not new.
App.js
window.App = Ember.Application.create();
App.Router.reopen({
location: 'history'
});
// Router
App.Router.map(function() {
this.resource('shops', function() {
this.route('new');
});
this.resource('shop', { path: '/shops/:shop_id' });
});
App.ShopsRoute = Ember.Route.extend({
model: function() {
return App.Shop.find();
}
});
App.ShopsNewRoute = App.ShopsRoute.extend({
model: function() {
return App.Shop.createRecord();
},
setupController: function( controller, model ) {
return this._super(),
controller.set( 'content', model )
}
});
App.ShopsNewController = Ember.ObjectController.extend();
// Models
App.Store = DS.Store.extend({
revision: 11,
adapter: DS.RESTAdapter
});
App.Shop = DS.Model.extend({
name: DS.attr('string'),
body: DS.attr('string'),
});
Index.html
<!DOCTYPE html>
<html>
<head>
<title>Ember/Rails App</title>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
<body>
<script type="text/x-handlebars" data-template-name="application">
<div class="row">
<div class="twelve columns">
<h1>Ordr</h1>
<hr>
{{outlet}}
</div>
</div>
</script>
<script type="text/x-handlebars" data-template-name="shops/new">
<h2>New Shop</h2>
</script>
<script type="text/x-handlebars" data-template-name="shops">
{{#each shop in controller}}
{{#linkTo "shop" shop}} {{ shop.id }}{{/linkTo}}
{{/each}}
{{#linkTo 'shops.new'}}Create{{/linkTo}}
</script>
<script type="text/x-handlebars" data-template-name="shop">
<h2>{{name}}</h2>
<p>{{body}}</p>
</script>
</body>
</html>
The way you have set up your routes and templates, you are telling Ember that you want to navigate to shops.new and keep all the list of shops showing even while you are in shops.new.
If that is in fact the scenario that you want, all you need to do is add an {{outlet}} inside the shops template:
<script type="text/x-handlebars" data-template-name="shops">
{{#each shop in controller}}
{{#linkTo "shop" shop}} {{ shop.id }}{{/linkTo}}
{{/each}}
{{#linkTo 'shops.new'}}Create{{/linkTo}}
{{outlet}}
</script>
However, if that is not what you really intend, and you actually want the list of shops to be hidden when you transition to shops.new, then you will need to change a couple of things.
change your App.ShopsRoute to App.ShopsIndexRoute :
App.ShopsIndexRoute = Ember.Route.extend({
model: function() {
return this.store.find('shop');
}
});
and your shops template to shops/index template:
<script type="text/x-handlebars" data-template-name="shops/index">
{{#each shop in controller}}
{{#linkTo "shop" shop}} {{ shop.id }}{{/linkTo}}
{{/each}}
{{#linkTo 'shops.new'}}Create{{/linkTo}}
</script>
Any of those 2 methods should fix your problem, depending on what your intentions are.