template not bind a model in Ember - ember.js

I will try to bind model,controller and template in ember
Here is my js
App = Ember.Application.create({});
App.Person = Ember.Object.extend({
firstName: "r",
lastName: "issa"
});
App.TestingRoute = Ember.Route.extend({
model: function () {
return App.Person.create();
},
setupController: function (controller, model) {
controller.set("model", model);
}
});
App.TestingController = Ember.ObjectController.extend({
submitAction: function () {
alert("My model is :" + this.get("model"));
}
});
my template is :
<script type="text/x-handlebars" data-template-name="application">
{{render testing}}
</script>
<script type="text/x-handlebars" data-template-name="testing">
{{input valueBinding="model.firstName"}}
{{input valueBinding="model.lastName"}}
<button {{action submitAction target="controller"}} class="btn btn-success btn-lg">Pseudo Submit</button>
<p>{{model.firstName}} - {{model.lastName}}</p>
</script>
what s wrong why model not binding in template and alert retunn model is null

Your setupController and model methods from TestingRoute aren't being called. Because your controller is created by the render view helper, not by a transition.
For example using the following works:
template
<script type="text/x-handlebars" data-template-name="testing">
{{input valueBinding="model.firstName"}}
{{input valueBinding="model.lastName"}}
<button {{action submitAction target="controller"}} class="btn btn-success btn-lg">Pseudo Submit</button>
<p>{{model.firstName}} - {{model.lastName}}</p>
</script>
javascript
App = Ember.Application.create({});
App.Router.map(function() {
this.route('testing', { path: '/' })
});
App.Person = Ember.Object.extend({
firstName: "r",
lastName: "issa"
});
App.TestingRoute = Ember.Route.extend({
model: function () {
return App.Person.create();
},
setupController: function (controller, model) {
debugger
controller.set("model", model);
}
});
App.TestingController = Ember.ObjectController.extend({
actions: {
submitAction: function () {
alert("My model is :" + this.get("model"));
}
}
});
Here is the fiddle http://jsfiddle.net/marciojunior/8DaE9/
Also, the use of actions in controllers is deprecated in favor of using the actions: { ... } object

Related

Ember.js clear controller on transitionToRoute call

I have a route that displays a list of parcels, and an Ember.Select that allows the user to select which state's parcels to show.
Model
App.Parcel = DS.Model.extend({
addresses: DS.attr('array')
});
Route
App.ParcelsRoute = Ember.Route.extend({
state: null,
renderTemplate: function () {
this.render({ outlet: 'parcels' });
},
model: function (params) {
state = params.state;
App.ParcelAdapter.state = state;
App.ImageAdapter.state = state;
return Ember.RSVP.hash({
props: this.store.findAll('parcel'),
states: this.store.findAll('state'),
});
},
setupController: function (controller, model) {
controller.set('states', model.states);
controller.set('props', model.props);
controller.set('selectedState', state);
}
});
Controller
App.ParcelsController = Ember.ObjectController.extend({
selectedState: null,
props: null,
states: null,
first: true,
modelReloadNeeded: function () {
if (this.get('selectedState') != undefined && !this.get('first')) {
this.transitionToRoute('/parcels/' + this.get('selectedState'));
}else{
this.set('first', false);
}
}.observes('selectedState')
});
Handlebars
<script type="text/x-handlebars" id="parcels">
{{view Ember.Select content=states optionValuePath="content.id" optionLabelPath="content.id" value=selectedState}}
<input class="search" placeholder="Search"/>
<ul class="list nav">
{{#each props}}
<li>{{#link-to 'parcel' this}}<h3 class="name">{{addresses.0.street_address}}</h3>{{/link-to}}</li>
{{/each}}
</ul>
</script>
When the select transitions to the new route, both the old routes data and new routes are in the model, but if I reload the page, only the current routes data is loaded. Is there a way to clear the DS.RecordArray for props in the controller without a location.reload() call?

Ember.js link-to inside #each block does not render

<script type="text/x-handlebars" data-template-name="application">
<ul>
{{#each person in controller}}
<li>{{#link-to 'foo' person}}{{person.firstName}}{{/link-to}}</li>
{{/each}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="foo">
<h5>Foo route</h5>
{{name}}: converted to {{fullName}}
</script>
javascript:
App = Ember.Application.create({});
App.ApplicationRoute = Ember.Route.extend({
model: function(){
return [
{firstName: 'Kris', lastName: 'Selden'},
{firstName: 'Luke', lastName: 'Melia'},
{firstName: 'Formerly Alex', lastName: 'Matchneer'}
];
}
});
App.Router.map(function() {
this.route('foo');
});
App.FooRoute = Ember.Route.extend({
model: function(params) {
// just ignore the params
return Ember.Object.create({
name: 'something'
});
}
});
App.FooController = Ember.ObjectController.extend({
fullName: function() {
return this.get('name') + ' Jr.';
}
});
I must be doing something wrong, because these {{#link-to}}'s are failing. Here's a JSBin. Hesitating to file an issue because this seems like such a simple thing:
http://jsbin.com/ucanam/4777/edit?html,js,output
Your route does not allow parameter. Change it to
this.resource('foo', { path: '/:person_id'});

Pass Iterating Object to Controller Method

When trying to pass an iterating object to the Controller method, the object is passed as a String.
Template:
<script type="text/x-handlebars" data-template-name="gradebooks">
{{#each}}
{{#link-to "gradebook" this}}{{title}}{{/link-to}}
{{/each}}
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="gradebook">
<h1>Student Grades</h1>
{{#each student in students}}
{{#each assignment in assignments}}
{{student.name}}, {{assignment.name}}: {{getGrade student assignment}}%
{{/each}}
{{/each}}
</script>
Routes:
App.Router.map(function() {
this.resource('gradebooks', function() {
this.resource('gradebook', { path: ':gradebook_id' });
})
});
App.GradebooksRoute = Ember.Route.extend({
model: function() {
return this.store.find(App.Gradebook);
}
});
App.GradebookRoute = Ember.Route.extend({
model: function(params) {
return this.store.find(App.Gradebook, params.gradebook_id);
}
});
Controller:
App.GradebookController = Ember.ObjectController.extend({
getGrade: function(student, assignment) {
console.log(student, assignment);
return 5;
}
});
Model:
App.Gradebook = DS.Model.extend({
title: DS.attr('string'),
students: DS.hasMany('student', { async: true}),
assignments: DS.hasMany('assignment', { async: true})
});
App.Student = DS.Model.extend({
name: DS.attr('string'),
gradebook: DS.belongsTo('gradebook'),
grades: DS.hasMany('grade', { async: true })
});
App.Assignment = DS.Model.extend({
name: DS.attr('string'),
gradebook: DS.belongsTo('gradebook'),
grades: DS.hasMany('grade', { async: true })
});
App.Grade = DS.Model.extend({
score: DS.attr('number'),
student: DS.belongsTo('student'),
assignment: DS.belongsTo('assignment')
});
Currently, the above outputs the string "student" for each student. If I were to have {{getGrade student.id}}, it would output the string "student.id". How could I get it to pass the student as an object?
Given your revision I've revised my answer below to better align:
App.AssignmentController = Ember.ObjectController.extend({
needs: ["student"],
getGrade: function() {
var student = this.get('controllers.student');
//logic to get grade
}.property() //thing to observe for changes
});
<script type="text/x-handlebars" data-template-name="gradebooks">
<h1>Student Grades</h1>
{{#each}}
{{#link-to "gradebook" this}}{{title}}{{/link-to}}
{{/each}}
</script>
<script type="text/x-handlebars" data-template-name="gradebook">
{{#each student in students}}
{{render 'student' student}}
{{/each}}
</script>
<script type="text/x-handlebars" data-template-name="student">
{{name}}
{{#each assignment in assignments}}
{{render 'assignment' assignment}}
{{/each}}
</script>
<script type="text/x-handlebars" data-template-name="assignment">
{{name}}: {{getGrade}}%
</script>
A useful tool is {{log model}} or {{log record}} or {{log ...whatver..}} to understand what data your view is receiving.
If you open the Chrome Ember Inspector you should also see what views, controllers, routes, models, etc. have been defined which will help with understanding.
In short you cannot pass parameters to controllers by using {{getGrade student.id}} - you can define a Handelbars helper to accept parameters but I don't think this is what you are after. The method above worked for me.
Hope this helps

how to create a right structure for nested routes in ember.js?

I need to create an application with routes:
/users - list of users
/users/123 - user info
/users/123/items - list of user items
/users/123/items/456 - items info
I wrote this code here
$(function() {
var App = window.App = Ember.Application.create({LOG_TRANSITIONS: true});
App.Router.map(function() {
this.resource("users", {path: '/users'}, function() {
this.resource("user", {path: '/:user_id'}, function() {
this.resource("items", {path: '/items'}, function() {
this.route("item", {path: '/:item_id'});
});
});
});
});
App.Store = DS.Store.extend({
revision: 11,
adapter: "DS.FixtureAdapter"
});
//ROUTES
App.UsersIndexRoute = Ember.Route.extend({
model: function() {
return App.User.find();
}
});
App.UsersUserIndexRoute = Ember.Route.extend({
model: function(params) {
return App.User.find(params.user_id);
},
setupController: function(controller, model) {
controller.set('content', model);
}
});
//DATA
App.User = DS.Model.extend({
name: DS.attr('string'),
items: DS.hasMany('App.Item')
});
App.Item = DS.Model.extend({
name: DS.attr('string')
});
App.User.FIXTURES = [
{
id: 1,
name: 'Joe',
items: [1, 2]
}, {
id: 2,
name: 'John',
items: [2, 3]
}
];
App.Item.FIXTURES = [
{
id: 1,
name: 'Item 1',
}, {
id: 2,
name: 'Item 2',
}, {
id: 3,
name: 'Item 3',
}
];
return true;
});
And templates:
<script type="text/x-handlebars" data-template-name="application">
<div>
<h1>ember routes</h1>
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" data-template-name="index">
<h2>Hello from index</h2>
{{#linkTo 'users'}}users area{{/linkTo}}
</script>
<script type="text/x-handlebars" data-template-name="users">
<h2>users area</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="users/index">
<h3>users list</h3>
{{#each user in controller}}
{{#linkTo "user" user}}{{user.name}}{{/linkTo}}<br/>
{{/each}}
</script>
<script type="text/x-handlebars" data-template-name="users/user">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="users/user/index">
<h4>user {{name}} index</h4>
</script>
<script type="text/x-handlebars" data-template-name="users/user/items">
<h4>user {{name}} items</h4>
{{outlet}}
</script>
If I go to /users , I see a list of users - its ok.
If I go to /users/1 I see message in browser console: "Transitioned into 'users.user.index'", but the content of the template 'users/user/index' is not showing.
I do not understand why, because I have App.UsersUserIndexRoute
Maybe I missed something?
if i'm not mistaken, using a UserIndexRoute (instead of a UsersUserIndexRoute - routes that are defined as resources usually don't have their parent routes' names prepended) with the model hook
model: function(params) {
return this.modelFor("user");
}
(and a corresponding template) should do the trick.

Trigger an action in a text field from a button

I'm looking for advice on how to trigger this view function insertNewLine from a button (see view and template below). I'm guessing there's probably a better way to structure this code. Thanks for your help.
// view
App.SearchView = Ember.TextField.extend({
insertNewline: function() {
var value = this.get('value');
if (value) {
App.productsController.search(value);
}
}
});
// template
<script type="text/x-handlebars">
{{view App.SearchView placeholder="search"}}
<button id="search-button" class="btn primary">Search</button>
</script>
You could use the mixin Ember.TargetActionSupport on your TextField and execute triggerAction() when insertNewline is invoked. See http://jsfiddle.net/pangratz666/zc9AA/
Handlebars:
<script type="text/x-handlebars">
{{view App.SearchView placeholder="search" target="App.searchController" action="search"}}
{{#view Ember.Button target="App.searchController" action="search" }}
Search
{{/view}}
</script>
JavaScript:
App = Ember.Application.create({});
App.searchController = Ember.Object.create({
searchText: '',
search: function(){
console.log('search for %#'.fmt( this.get('searchText') ));
}
});
App.SearchView = Ember.TextField.extend(Ember.TargetActionSupport, {
valueBinding: 'App.searchController.searchText',
insertNewline: function() {
this.triggerAction();
}
});