EmberJS client side record management (ember-data) - ember.js

I have just started trying to use ember-data. I have an ember app for which I need to produce all the data on the client side and then save it all at once. So my object graph has a "Project" as the root object, then a project can have many "Sections" and then each section can have many "Items".
I am up to the stage where I am trying to create Item records on the client side and add them to the correct Section. When I am ready to save the data I just want to use project.save() and have it go and save the object graph instead of saving every time the model changes.
I am trying to look up the section to place the items in by name using store.filter({name:"section1"}) but ember keeps trying to go to the server to look them up. I see this in the console: GET http://localhost:4200/sections?name=Section1 404 (Not Found).
This is what I am trying to do:
store.filter('section', {name:'Section1'}, function(section) {
return section;
}).then(function(section)
{
var record;
//create a record
section.pushObject(record);
});

You are doing server side filtering and you want client side filtering.
Please read this article carefully.
In short, you should do
store.filter('section', function(section) {
return section.get('name') == 'Section1';
});

Related

ember-data 2.0 and Offline

I am creating a new ember app. I want to use the newest version of ember-data. (ember-data 2.0). I want it to be a mobile webapp. Therefore it must handle variable network access and even offline.
I want it to store all data locally and use that data when it goes offline so the user gets the same experience regardless of the network connectivity.
Is ember-data 2.0 capable of handling the offline case? Do I just make an adapter that detects offline/online and then do....?
Or do I have to make my own in-between layer to hide the offline handling from ember-data?
Are there any libraries out there that has this problem solved? I have found some, but are there any that is up to date with the latest version of ember-data?
If device will go offline and user will try to transition to route, for which model is not loaded yet, you will have an error. You need to handle these situations yourself. For example, you may create a nice page with error message and a refresh button. To do this, you need:
First, In application route, create error action (it will catch errors during model hook), and when error occurs, save transition in memory. Do not try to use local storage for this task, it will save only properties, while we need an actual transition object. Use either window.failedTransition or inject in controllers and routes a simple object, which will contain a failed transition.
actions: {
error: function (error, transition) {
transition.abort();
/**
* You need to correct this line, as you don't have memoryStorage
* injected. Use window.failedTransition, or create a simple
* storage, Iy's up to you.
*/
this.get('memoryStorage').set('failedTransition', transition);
return true; //This line is important, or the whole idea will not work
}
}
Second, Create an error controller and template. In error controller define an action, retry:
actions: {
retry: function () {
/**
* Correct this line too
*/
var transition = this.get('memoryStorage').getAndRemove('failedTransition');
if (transition !== undefined) {
transition.retry();
}
}
}
Finally, In error template display a status and an error text (if any available) and a button with that action to retry a transition.
This is a simple solution for simple case (device gone offline just for few seconds), maybe you will need something way more complex. If you want your application to fully work without a network access, than you may want to use local storage (there is an addon https://github.com/funkensturm/ember-local-storage) for all data and sync it with server from time to time (i.e sync data every 10 sec in background). Unfortunately I didn't try such things, but I think it is possible.

Ember Data - ArrayController's content does not reload, after adding new items by store.pushPayload method

I have a list of items handling by Ember.ArrayController. I'm doing some PATCH action on records, which updates existing items and adding a new ones, if it is needed from the context. All changes I'm sending back from the server and I'm pushing it to the store by using Store.pushPayload() method.
I do something like that:
All changes in existing records are automatically updated - so observers of particular items are run.
Unfortunately when I have a new items in payload - they do not appear on the list - observes of ArrayController.content are not called.
I also tried to manually notify ArrayController about the changes by doing:
_this.store.pushPayload(response);
var tasksController = _this.get('controllers.tasks');
tasksController.contentDidChangedManually();
And in controller:
contentDidChangedManually: function() {
this.set('contentChangedManually', new Date().getTime());
},
filteredContent: function() { // my content filters... }.property('arrangedContent', 'contentChangedManually')
But it does not work, because contentDidChangedManually() is run before pushing a payload is done. Unfortunately, Store.pushPayload() does not return a promise, so I can't run it when new records are ready.
Does anyone have a solution for this? Thanks in advance.
It sounds as if you are using find to load your model data, you likely want to use DS.Store.filter instead as that returns a live updating record array:
http://emberjs.com/api/data/classes/DS.Store.html#method_filter

Microsoft Dynamics CRM - Pass Parameters from Web Service to IPlugins

We are building some plugins in Microsoft Dynamics CRM by inheriting from IPlugin. We have these configured so they fire whenever an Account is updated.
The problem is the plugins are calling our services, which causes our service to respond with an update. We are doing some pretty hacky things right now to prevent these cyclical updates from happening.
We were wondering if there was a way to pass a value to the IOrganizationService service (the web service) that a plugin can look at. Our other system could send a flag ("hey, don't bothing sending an update!") and the plugin could skip calling back.
Can we pass parameters from web service to the plugins?
Good idea could be usage of custom flag-field. For example you add bit field and call it CallFromExternalSystem. So when you make an update from your external system through IOranizationService you just fill this flag with true field and in plugin you can check condition that this field is present in fields list so you have no need to call external system endpoint again.
We decided the correct solution was to use the value found in IPluginExecutionContext.InputParameters["Target"]. In the case of an Update, this returns an Entity containing attributes for all the attributes that were updated.
We basically have a list of attribute names we cared about. We loop through names and see if any of them appear in the entity attribute list. If so, we send an update to our other system. The good news is, Dynamics CRM ignores updates where the values don't actually change, so trying to update a value to itself is no-op.
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = serviceProvider.GetService(typeof(IPluginExecutionContext));
Entity entity = (Entity)context.InputParameters["Target"];
string[] fields = new string[] { "name", "statecode", "address1_line1" };
bool hasUpdates = fields.Where(f => entity.Attributes.Contains(f)).Any();
if (!hasUpdates)
{
return;
}
}

How can I force ember-data to refresh an object after committing it?

I'm submitting an object to our API via a POST and then transitioning to a route that displays that object. The API modifies one or more fields in the object in the POST and returns the updated info in the request response.
The data displayed is the original data from before the POST to our API. I can see from the console that ember-data is receiving back the updated information from our API. How can I force ember to "refresh" the object so that it displays the correct info?
Matt. Yehuda Katz posted a reply to a user which provides this functionality:
https://stackoverflow.com/a/14183507/506230
Basically you create a record, apply it, save it, then reload it.
saveMessage: function(text){
var acct = Social.Account.find(this.get("id")),
msg = Social.store.createRecord(
Social.Message,
{
text: text,
account: acct,
created: new Date()
}
);
acct.get("messages").addObject(msg);
Social.store.commit();
var timeoutID = window.setTimeout(function(){
__msg.reload();__
console.log('reloading');
}, 250);
}
It turns out ember was actually behaving properly and no additional work was necessary. The problem is that I was setting a variable on the controller with the same name as a computed property on my model. The value of the variable on the controller was being displayed rather than the computed property. Changing the name of the controller variable resolved the issue without any additional code.

Retrieve service information from WFS GetCapabilities request with GeoExt

This is probably a very simple question but I just can't seem to figure it out.
I am writing a Javascript app to retrieve layer information from a WFS server using a GetCapabilities request using GeoExt. GetCapabilities returns information about the WFS server -- the server's name, who runs it, etc., in addition to information on the data layers it has on offer.
My basic code looks like this:
var store = new GeoExt.data.WFSCapabilitiesStore({ url: serverURL });
store.on('load', successFunction);
store.on('exception', failureFunction);
store.load();
This works as expected, and when the loading completes, successFunction is called.
successFunction looks like this:
successFunction = function(dataProxy, records, options) {
doSomeStuff();
}
dataProxy is a Ext.data.DataProxy object, records is a list of records, one for each layer on the WFS server, and options is empty.
And here is where I'm stuck: In this function, I can get access to all the layer information regarding data offered by the server. But I also want to extract the server information that is contained in the XML fetched during the store.load() (see below). But I can't figure out how to get it out of the dataProxy object, where I'm sure it must be squirreled away.
Any ideas?
The fields I want are contained in this snippet:
<ows:ServiceIdentification>
<ows:Title>G_WIS_testIvago</ows:Title>
<ows:Abstract/>
<ows:Keywords>
<ows:Keyword/>
</ows:Keywords>
<ows:ServiceType>WFS</ows:ServiceType>
<ows:ServiceTypeVersion>1.1.0</ows:ServiceTypeVersion>
<ows:Fees/>
<ows:AccessConstraints/>
Apparently,GeoExt currently discards the server information, undermining the entire premise of my question.
Here is a code snippet that can be used to tell GeoExt to grab it. I did not write this code, but have tested it, and found it works well for me:
https://github.com/opengeo/gxp/blob/master/src/script/plugins/WMSSource.js#L37