Different result from App.Model.find() and App.Model.find({params}) - ember.js

I'm trying to create a todo-app (original, right?) and have a problem that ember doesn't display my newly created objects if use find({some parameters}) instead of find().
The problem seems to be that App.Model.find() returns a different result than, for example, App.Model.find({checked: false}).
I've created TasksRoute and defined the model data as App.Task.find().
When using App.Task.find() I can create a new task by typing:
var task = App.Task.createRecord({name: "taskName"});
task.get("store").commit();
The list is updated and the view displays the newly created task.
But if I instead use App.Model.find({}), or with any other hash, and then create a task nothing happens.
Here's the html:
<script type="text/x-handlebars" data-template-name="application">
{{#linkTo "tasks"}}Tasks{{/linkTo}}
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="tasks">
{{#each controller}}
{{name}}<br />
{{/each}}
</script>
Javascript:
App = Em.Application.create();
App.Store = DS.Store.extend({
revision: 12,
adapter: DS.RESTAdapter.create({url: "http://localhost/backend/"})
});
App.Task = DS.Model.extend({
name: DS.attr('string')
})
App.TasksRoute = Ember.Route.extend({
model: function() {
return App.Task.find();
}
});
App.Router.map(function(){
this.route('tasks');
});
App.TasksController = Em.ArrayController.extend({});
The reason that I don't want to use find() is that I want to be able to specify my query. For example I would like to be able to retrieve all tasks that are checked by providing a hash to find().
(I tried creating a jsFiddle but didn't manage to get it to work with fixtures)
Is this a bug or have I done something wrong?
Thanks in advance

You might want to use filterProperty('checked', false) instead of find({params})

Related

Multiple Highcharts based charts using ember.js

My requirement is as follows:
I will be intially fetching my list of reports which will contain only the report Id.Based on the report Id, I need to fetch the data for each report .I have partially succeeded in achieving this requirement. Please find the link below:
http://jsbin.com/ditazibowe/1/edit
Now I need to somehow pass the reportId from my template to my model , so that it fetches the data for each report based on the id. Is this possible to achieve? Any pointers will be helpful.
Thanks in advance.
Modify the model a bit and replace all calls to jquery $ with this.$ in order to use the context of the specific context.
example,
http://jsbin.com/zawameqilo/1/edit?html,js,output
js
App.IndexRoute = Ember.Route.extend({
model:function()
{
var reportModel = [];
reportData.forEach(function(reportDataItem){
var reportDataObject = Ember.Object.create({});
reportDataObject.reopen({
reportId:reportDataItem.reportId,
chartOptions:{chart:{
type: 'line',
}},
graphData:function(){
return fetchData(this.get("reportId"));
}.property("reportId")
});
reportModel.pushObject(reportDataObject);
});
return reportModel;
}
});
....
this.$('.chart').highcharts(chart);
....
hbs
<script type="text/x-handlebars" data-template-name="index">
{{#each model}}
<h1>{{reportId}}</h1>
{{chart- chartOptions=chartOptions reportId=reportId series=graphData}}
{{/each}}
</script>

Ember route map url with query parameters

this is my route configuration (route.js using ember-cli)
this.resource('xero-invoices', {path:'/loans/xero/:loan_id/invoices'})
but ember cuts query string when trying to route this address . How to fix problem?
The portion of your route definition had a minor typo missing a closing curly brace, but I am assuming that is not really the issue. Here it is fixed for clarity.
this.resource('xero-invoices', {path:'/loans/xero/:loan_id/invoices'})
The resource above has a dynamic segment of lone_id not a query string. Query string support is currently in the beta builds of Ember and not in stable. Any query string functionality you are trying to use would be handled in your controller. http://emberjs.com/guides/routing/query-params/
If you had a jsbin or more code I may be more helpful.
Here is a trivial jsbin showing the dynamic segment working - http://emberjs.jsbin.com/casana/1/edit
Edit:
In your example jsbin you are trying to use the (query-parms) helper for link-to which is only available if you are using the beta version of Ember. In your application controller if you remove it from your application template you won't get an error. In your route, since you are returning the query param as the model, the oauth_token is accessible via the model property in the controller.
Source: http://jsbin.com/bufukiqisika/8/edit
App = Ember.Application.create();
App.Router.map(function() {
this.resource('xero-invoices', { path:'/loans/xero/:loan_id/invoices' });
});
App.IndexRoute = Ember.Route.extend({
model: function() {
return ["red","blue","green"];
}
});
App.XeroInvoicesRoute = Ember.Route.extend({
model: function(params) {
window.console.log(params);
return params.queryParams["oauth_token"];
}
});
Templates:
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="xero-invoices">
{{model}}
</script>
Example: http://jsbin.com/bufukiqisika/8#/loans/xero/09870987/invoices?oauth_token=foo
You can use query-parameters which are defined on controllers.
Something like this should work:
MyController = Ember.Controller.extend({
queryParams: ['searchvalue'],
searchvalue : null
})
And in you Template:
{{input type="text" valueBinding=controller.searchvalue}}
So your search value will be represented in the URL, e.g. “…/myapp/seach?searchvalue=foo”
See http://emberjs.com/guides/routing/query-params/

Dynamic value in application template

I tried to implement user name displaying after log in. It displays in top menu. But top menu is getting displayed before log in, so it user name is getting cached.
I tried many approaches, and using volatile() is seems the best option, but it doesn't work. In this simple example currentTime calculates only once:
<script type="text/x-handlebars" data-template-name="application">
{{currentTime}}
</script>
App.ApplicationController = Ember.Controller.extend({
currentTime: function() {
console.log('computing value');
var time = new Date();
return time;
}.property().volatile()
});
Ember version 1.3
P.S. I prepared the gist to illustrate this issue: http://jsbin.com/OPUSoTaF/1
Actually, I can't find ANY way do display dynamic value in Ember's application template. Tried to display value from another controller using {{render}} helper, value still gets cached.
It seems that I just need to update value on ApplicationController from some other controller, and to do it in a proper way. Like this:
App.LoginController = Ember.Controller.extend({
needs: 'application',
setTime: function() {
this.get('controllers.application').set('currentTime', new Date());
}
});
The application to illustrate: http://jsbin.com/OPUSoTaF/4/edit
You can change ember properties and thus views using Handlebars {{action 'actionName'}} helper. You can add action helper to almost any UI element in your handlebars template an it is usually triggered on click. When triggered it calls actionName method on the controller.
Example:
Handlebars template:
<script type="text/x-handlebars" data-template-name="application">
<button {{action 'login'}}>Login</button>
{{loginTime}}
</script>
Controller:
App.ApplicationController = Ember.Controller.extend({
loginTime: 'User not logged in yet',
actions: {
login: function() {
// ... Do some login stuff ...
this.set('loginTime', new Date());
}
}
});
Working jsbin example is here: http://jsbin.com/udUyOXaL/1/edit

Ember.js: how to use an ArrayController to describe multiple models?

I am trying to set up a dashboard that can monitor and display information on multiple models. The ArrayController seems like the correct object to use, but I am not sure what I am doing wrong.
Can someone explain where I've gone astray here?
jsBin Example: http://jsbin.com/IgoJiWi/8/edit?html,js,output
javascript:
App = Ember.Application.create();
/* ROUTES */
App.Router.map(function() {
this.resource('options');
this.resource('dashboard');
});
App.IndexRoute = Ember.Route.extend({
redirect: function() {
this.transitionTo('options');
}
});
App.OptionsRoute = Ember.Route.extend({
model: function() {
var a = Em.A();
a.pushObject( App.Options.create({title: 'A', cost: '100'}));
a.pushObject( App.Options.create({title: 'B', cost: '200'}));
a.pushObject( App.Options.create({title: 'C', cost: '300'}));
return a;
}
});
/* MODELS */
App.Options = Ember.Object.extend({
title: '',
cost: '',
quantity: ''
});
/* CONTROLLERS */
App.optionsController = Ember.ArrayController.extend({
legend: 'test',
len: this.length,
totalCost: function() {
return this.reduce( function(prevCost, cost, i, enumerable){
return prevCost + cost;
});
}.property('#each.cost')
});
handlebars:
<script type="text/x-handlebars" data-template-name="application">
<p><strong>Ember.js example</strong><br>Using an ArrayController to access aggrigated data for all models of type X.</p>
{{render dashboard}}
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="options">
<h2>Options:</h2>
<dl>
{{#each}}
<dt>Title: {{title}}</dt>
<dd>Cost: {{cost}} {{input value=cost}}</dd>
{{/each}}
</dl>
</script>
<script type="text/x-handlebars" data-template-name="dashboard">
<h2>Overview:</h2>
<p>Why won't this display info about the options below? I suspect that the optionsController does not actually contain options A-C...</p>
{{#with App.optionsController}}
<p>Total number of options (expect 3): {{len}}</p>
<p>Total cost of options (expect 600): {{totalCost}}</p>
{{/with}}
</script>
Without getting into the why of doing things this way, there were a couple problems with making it just work.
optionsController needs to be OptionsController
the active controller in the dashboard will be DashboardController (autogenerated if not defined) so you need to open that and give it a reference to options
in reduce, the second argument is an item reference, so you need to do get('cost') on it
in order for javascript to know you want integer math, you need to use parseInt
This is a working jsbin: http://jsbin.com/acazAjeW/1/edit
lol, kingpin2k and I seem to be competing for answering ember questions these days.
Part of the problem is, your dashboard exists even when the options may not, which might be the route you are going in the future, here's a partial version that works, I'll look into the other version.
http://jsbin.com/ImOJEJej/1/edit
Using render
http://jsbin.com/ImOJEJej/3/edit

Ember -- TypeError: arrangedContent.addArrayObserver is not a function

I am trying to build a simple category browser with ember. I have two very simple views. When the user visits / they will see a list of all categories and when they click a category in that list they will be directed to #/10 where 10 is the id.
My problem is that when a user clicks on a category at the / route I am getting the following error
TypeError: arrangedContent.addArrayObserver is not a function
[Break On This Error]
didChange: 'arrangedContentArrayDidChange'
If I refresh the page at the #/10 route the proper api call is made to my backend /api/categories?parent=99. What could I be doing wrong that is throwing this error during the transition? A full example of my code is below.
Templates:
<script type="text/x-handlebars">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="categories">
{{#each category in controller}}
<p>{{#linkTo 'category' category}}{{ category.name }}{{/linkTo}}</p>
{{/each}}
</script>
<!--this is an array instead of object -->
<script type="text/x-handlebars" data-template-name="category">
{{#each category in controller}}
<p>{{category.name}}</p>
{{/each}}
</script>
Javascript:
var App = Ember.Application.create();
App.Router.map(function(){
this.resource('categories', { path : '/' });
this.resource('category', { path : '/:category_id' });
});
App.CategoriesRoute = Ember.Route.extend({
model: function(){
return App.Category.find();
}
});
//this is causing the error possibly
App.CategoryRoute = Ember.Route.extend({
model: function(params){
return App.Category.find({parent: params.category_id});
}
});
App.CategoryController = Ember.ArrayController.extend();
// Models
App.Store = DS.Store.extend({
revision: 11,
adapter: 'DS.RESTAdapter'
});
DS.RESTAdapter.configure("plurals", {
category: "categories"
});
App.Category = DS.Model.extend({
name: DS.attr('string'),
parent_id: DS.attr('number')
});
Debug info:
DEBUG: Ember.VERSION : 1.0.0-rc.1
DEBUG: Handlebars.VERSION : 1.0.0-rc.3
DEBUG: jQuery.VERSION : 1.9.0
Hint: After writing this i realized that you probably did not get the model hook right. This hook is called when you are entering your app via url. It converts the URL into an appropriate model and transition with this model into the Route. I guess you thought that this model() hook would be called with the arguments of {{#linkTo}}? This is not the case!
This does not work because you are passing a single model to your #linkTo helper in your template. So Ember wants to set this single object as content of your ArrayController. This causes your error. And your model hook returns an array. Rule of Thumb: You should always pass the same data structure to #linkTo, which you are returning in your model hook.
Therefore i would suggest to use an event instead of linkTo and do the following:
<script type="text/x-handlebars" data-template-name="categories">
{{#each category in controller}}
<p {{action 'showParentCategory' category}}>{{category.name}}</p>
{{/each}}
</script>
App.CategoriesRoute = Ember.Route.extend({
model: function(){
return App.Category.find();
},
events: {
showParentCategory : function(parentCategory){
var cats = App.Category.find({parent: parentCategory.get("category_id")});
this.transitionTo("category", cats);
}
}
});
What have i done here?
I created an action called "showParentCategory".
As this is an action with is about routing, i am handling this event in your CategoriesRoute. As you see, events/action handlers are declared in the events property of your route.
I am performing the same logic there as in your model hook and then i am calling manually the transitinTo with the fetched categories.
UPDATE: How to serialize
By implementing serialize, you are telling Ember what to put into your url.
App.CategoryRoute = Ember.Route.extend({
model: function(params){
return App.Category.find({parent: params.category_id});
},
serialize : function(models){
var first = models.objectAt(0);
return {
category_id : first.get("parentId")
}
}
});
If you do #each over a numeric value instead of doing it on an array content in your template, this issue occurs.
I had a numeric value count in my 'poll' model . I was iterating like,
{{#each poll in content.count}}
{{/each}}
I think, we have to use #each only on ember arrays.