It depends on how many records you want to search and whether they have been loaded into the store.
Queries are useful for doing searches of hundreds, thousands, or even millions of records. You just
hand the search options to your server, and it is responsible for handing you back the list of records that match. Because the response from the server includes the ID of all of the records that matched, it doesn’t matter if the store hadn’t loaded them previously; it sees that they are not in the cache and can request the records by ID if necessary.
The downside of queries is that they do not live update, they are slower, and they require that your server support the kind of queries that you wish to perform.
Because the server decides which records match the query, not the store, queries do not live update. If you want to update them, you must manually callreload()and wait for the server to respond. If
you create a new record on the client, it will not show up in the results until you both save the new record to the server and reload the query results.
Because the store must confer with your server to determine the results of a query, it necessitates a network request. This can feel slow to users, especially if they are on a slow connection or your server is slow to respond. The typical speed of JavaScript web applications can heighten the perceived slowness when the server must be consulted.
Lastly, performing queries requires collaboration between the store and your server. By default, Ember Data will send the search options that you pass as the body of an HTTP request to your
¹⁷⁰https://github.com/search?q=ember+data+adapter&ref=cmdform
server. If your server does not support requests in this format, you will need to either change your server to do so, or customize how queries are sent by creating a custom adapter.
Filters, on the other hand, perform a live search of all of the records in the store’s cache. As soon as
a new record is loaded into the store, the filter will check to see if the record matches, and if so, add it to the array of search results. If that array is displayed in a template, it will update automatically. Filters also take into account newly created records that have not been saved, and records that have been modified but not yet saved. If you want records to show up in search results as soon as they are created or modified on the client, you should use a filter.
Keep in mind that records will not show up in a filter if the store doesn’t know about them. You can ensure that a record is in the store by using the store’spush()method.
There is also a limit to how many records you can reasonably keep in memory and search before you start hitting performance issues.
Finally, keep in mind that you can combine queries and filters to take advantage of their respective strengths and weaknesses. Remember that records returned by a query to the server are cached in the store. You can use this fact to perform a filter, passing it a query that starts matching records into the store, and a filter function that matches the same records.
This will offload searching all of the possible records to the server, while still creating a live updating list that includes records created and modified on the client.
1 App.PostsFavoritedRoute = Ember.Route.extend({
2 model: function() {
3 var store = this.store;
4
5 // Create a filter for all favorited posts that will be displayed in
6 // the template. Any favorited posts that are already in the store
7 // will be displayed immediately;
8 // Kick off a query to the server for all posts that
9 // the user has favorited. As results from the query are
10 // returned from the server, they will also begin to appear.
11 return store.filter('post', { favorited: true }, function(post) {
12 return post.get('isFavorited');
13 });
14 }
15 });
How do I inform Ember Data about new records created on the backend?
When you request a record using Ember Data’sstore.findmethod, Ember will automatically load
the data into the store. This allows Ember to avoid the latency of making a round trip to the backend next time that record is requested. Additionally, loading a record into the store will update any
RecordArrays (e.g. the result of store.filterorstore.all) that should include that record. This
means any data bindings or computed properties that depend on theRecordArraywill automatically
be synced to include the new or updated record values.
Some applications may want to add or update records in the store without requesting the record via
store.find. To accomplish this you can use theDS.Store’spush,pushPayload, orupdatemethods.
This is useful for web applications that have a channel (such asSSE¹⁷²orWeb Sockets¹⁷³) to notify it of new or updated records on the backend.
push¹⁷⁴is the simplest way to load records to Ember Data’s store. When usingpushit is important
to remember to deserialize the JSON object before pushing it into the store.pushonly accepts one
record at a time. If you would like to load an array of records to the store you can callpushMany¹⁷⁵. 1 socket.on('message', function (message) {
2 var type = store.modelFor(message.model);
3 var serializer = store.serializerFor(type.typeKey);
4 var record = serializer.extractSingle(store, type, message.data);
5 store.push(message.model, record);
6 });
pushPayload¹⁷⁶is a convenience wrapper forstore#pushthat will deserialize payloads if the model’s
Serializer implements apushPayloadmethod. It is important to note this method will not work with
theJSONSerializerbecause it does not implement apushPayloadmethod.
1 socket.on('message', function (message) {
2 store.pushPayload(message.model, message.data);
3 });
update¹⁷⁷works like apushexcept it can handle partial attributes without overwriting the existing
record properties. This method is useful if your web application only receives notifications of the changed attributes on a model. Likepushit is important to remember to deserialize the JSON object
before callingupdate.
¹⁷²http://dev.w3.org/html5/eventsource/ ¹⁷³http://www.w3.org/TR/2009/WD-websockets-20091222/ ¹⁷⁴http://emberjs.com/api/data/classes/DS.Store.html#method_push ¹⁷⁵http://emberjs.com/api/data/classes/DS.Store.html#method_pushMany ¹⁷⁶http://emberjs.com/api/data/classes/DS.Store.html#method_pushPayload ¹⁷⁷http://emberjs.com/api/data/classes/DS.Store.html#method_update
1 socket.on('message', function (message) {
2 var hash = message.data;
3 var type = store.modelFor(message.model);
4 var fields = Ember.get(type, 'fields');
5 fields.forEach(function(field) {
6 var payloadField = Ember.String.underscore(field);
7 if (field === payloadField) { return; }
8 hash[field] = hash[payloadField];
9 delete hash[payloadField];
10 });
11 store.push(message.model, hash);
## Introduction Because Handlebars templates in Ember.js are so powerful, the majority of your application’s user interface will be described using them. If you are coming from other JavaScript libraries, you may be surprised at how few views you have to create.
Views in Ember.js are typically only created for the following reasons: • When you need sophisticated handling of user events
• When you want to create a re-usable component
Often, both of these requirements will be present at the same time.
Event Handling
The role of the view in an Ember.js application is to translate primitive browser events into events that have meaning to your application.
For example, imagine you have a list of todo items. Next to each todo is a button to delete that item:
caption
The view is responsible for turning a primitive event (a click) into a semantic event: delete this todo! These semantic events are first sent up to the controller, or if no method is defined there, your application’s router, which is responsible for reacting to the event based on the current state of the application.