Ember Data and Northwind OData - ember.js

Could Ember-Data b3+ be used for work against a service like this, http://services.odata.org/V2/Northwind/Northwind.svc. If so, could anyone provide an example on how to use it to read OData.
For example a JSBin showing a list of customers where a customer list item can navigate to the orders of a clicked customer
I think this would be a great boon for developers working against different data protocols to wrap their heads around how to wire up an Ember application with Ember-Data.
I've done this with fixtures but just couldn't really wire it up with actual server data.

Edit
Since I wrote this, I have abandoned Ember and fell back to angular for my SPA data apps. The main reason behind this is Ember Set which you should use for Ember to wire up all its binding internals.
Unfortunately, this is not compatible with most libs like Jaydata or Breeze. At least not when you wish to make changes/saves to your entity service.
Jaydata and Breeze both use a propertyChanged property to monitor changes to your entity and Ember will prevent these changes with a You should use Ember Set error.
I could probably have written some sort of adapter to overcome this problem but really I didn't have time and I use a library "Ember" to make my life easier... not to have headaches on basics such as Data Service Queries.
So... I really love Ember, but unfortunately as long as they dont enhance "Ember Data" or drastically change the Ember Set policy, I can't use it!
Basically, if you plan to use a data library (JayData, Breeze) to update a backend...
DON'T USE EMBER!
Original
I had a look (very quickly!) at ember-data and wasnt thrilled really! It looks promising for Standard REST service which IMHO is not WCF's case.
I ended up using JayData for that purpose and I must say it integrates very well with Ember.
here is a quick snippet to get you going:
//Instanciate the Ember APP
App = Ember.Application.create();
//Tell the APP to initialize but to wait before launching
App.deferReadiness();
//Setup your JayData Store
//Entities.EntityModel was generated by JaySvcUtil
App.myStore = new Entities.EntityModel({
name: 'oData',
oDataServiceHost: <YOUR_WCF_ENDPOINT_URL>
});
//Create your route and populate model data
App.IndexRoute = Ember.Route.extend({
model: function () {
//This passes the toArray() promise to the model
return App.myStore.People.orderBy('it.Name').toArray();
}
});
//When JayData Store is ready, Fire the App
App.myStore.onReady(function () {
App.advanceReadiness();
});
Ember Route Model actually handles the promise given by JayData which allows us to just pass the query. see: http://emberjs.com/guides/routing/asynchronous-routing/#toc_the-router-pauses-for-promises

Related

Ember route communication with unrelated component

I know EmberJS promotes "data down, actions up", but I have a scenario that I'm not sure how to fit into that paradigm. It's best if I explain by an example that's analogous to what I'm trying to achieve.
Let's say I have a fixed header component ('fixed-header'). I want this header to appear always, so of course I add it to my main application template:
{{fixed-header}}
{{outlet}}
Now let's say I want my header to display some information about the route I'm on. For simplicity's sake, let's say each route has a title I want displayed in the fixed header. So whether I'm on /foo or /foo/bar/baz or /wackawacka/meh?cat=meow, I want that route to be able to send some data to fixed-header component to display. In other words, I kinda want to go against "data down" and do a "data up".
What is the ideal way to approach this? My first instinct was to create a service that my-header listens to and routes can post their information to. But is that the right thing to do? It seems weird to me to create a service just to send a little bit of text. Is there another way?
You could use a parameter for your component.
{{fixed-header info=headerInfo}}
{{outlet}}
And then in any route in some hook
setupController: function(controller, model) {
this._super(controller, model);
var headerInfo = ...
this.controllerFor('application').set('headerInfo', headerInfo);
}
Service is the way to go. refer Service Ember Guide
An Ember.Service is an Ember object that lives for the duration of the application, and can be made available in different parts of your application.
Services are useful for features that require shared state or persistent connections.

Ember js: Getting big amounts of data from a backend

Here is the problem: the request from the backend takes ~2s, but wrapping the data with ember models takes ~5s. Is there any way not to use Ember models at all? Pagination has already been implemented.
I've found https://github.com/ember-cli/ember-ajax but I'm not sure if it can help.
Maybe you should consider to use a Paging!
On the Server and/or on the Client!
Are you sure the wrapping is that costly, not the rendering? Glimmer at the current stage has a poor initial rendering performance. This will improve in future ember versions!
But you can use ember without ember-data if you want to!
Just return plain JS Structures in your model hooks, or anywhere you want it! So this will work:
model() {
return Ember.RSVP.resolve($.getJSON('/myUrl'));
}

Component to be notified on route change in EmberJS 2

My task is to develop a menu component for an Ember 2 app. This is going to be a complex component whose visual representation changes as the user goes through routes. For instance it should disable particular menu and all its items when on "/index" route but enable it and some of its items when on "/details" and so on.
So, I've got a component that is passed a singleton model (stored in a Service currently, btw, is it a right place to store globally available singleton models in Ember?). It displays the stuff well but it does not respect the current route nor catches the route changes as user goes through the app. How can I achieve it?
Summing it up:
The component needs to get current route somehow to be able to display its initial state, for instance the user bookmarked the "/details" page and visited it.
The component has to deal with route changes somehow.
Is a Service a good place to hold a singleton model (which could potentially be fetched from server).
Can you provide your thoughts on how to tackle the three above?
SOLVED: Ok, here's how it is done, thanks to #Bek's suggestions:
import Ember from "ember";
export default Ember.Component.extend({
router: Ember.inject.service("-routing"),
didInsertElement: function() {
let r = this.get("router");
console.log("Initial route", r.get("currentRouteName"));
r.addObserver("currentRouteName", this, "currentRouteNameChanged");
},
"currentRouteNameChanged": function(router, propertyName) {
console.log(router.get("currentRouteName"));
}
});
MORE QUESTIONS :) - I had to surround the currentRouteNameChanged function name with quotes (to make it a string) otherwise it was not called. I assume I miss something very basic and obvious here?
One more issue is the funky service name -routing - #Bek, any hints on how could I figure it out myself, is there a list of injectable stuff I could look up information in? It is not yet in Ember documentation I assume but where in the source code of it to check it out? How stable -routing name in general, would it become *routing or something in final version?
Answer to 1 and 2:
In latest versions of ember 2.x (in 2.2 at least) router is available as service so you can inject it to component router: Ember.inject.service('-routing') and observe changes on currentRouteName, but it is currently private service so should be used with caution as it might change (might be renamed to routing), there is also rfc https://github.com/emberjs/rfcs/pull/38 which proposes routable components which will be part of ember in the future.
Anser to 3:
Services usually stateless, but there can be exceptions and services made to share global logic/objects so it is not a bad idea

Ember-Data: Adding Server Queries to AJAX Requests

I am having trouble with a specific case using Ember-Data.
Typically Ember expects a model class, the route, the ajax request, and the returned JSON, to all follow a similar pattern.
The RESTAdapter tries to automatically build a URL to send to the server, which is ok for some situations, but I need full control over some of my request URLs particularly when it comes to appending additional parameters, or matching an API to a route that has a completely different URL structure.
Ember sadly, has no guides for this, though I did find something about the buildURL method
I am not comfortable enough rooting through the source code to find out what happens under the hood though I do not want to break ember data just to fix a few use cases.
I have set my RESTAdapter's namespace to api/rest
The model and resource I want to populate is view-debtors
The specific service I want to reach is at debtor/list
I also need to pass extra parameters for pagination ?page_size=10&page_number=1, for example.
I am completely lost how to do this. I cannot change the API structure... there are too many services depending on them.
Some Small Progress
I went ahead and used my current knowledge to get a little closer to the solution.
I created a model and called it "list"
I extended RESTAdapter for "list" to change the namespace to "api/rest/debtor"
I changed the model hook for "view-debtors" route to store.find('list')
The result now is that the AJAX call is almost correct... I just need to add those extra parameters to the server queries.
This is where I stand now... can I add those server queries via the model hook? or better yet can I also control server queries via ember actions to get new AJAX requests?
Stepping back a bit. Is my method so far a good practice? Because I am using a route's model hook, to set the model to list, will this only work if the routes URL is typed in directly?
So many questions :p
You can find by query which will append a query string onto the end of your request using the object provided.
// this would produce /api/rest/debtor/lists?page_size=1&page_number=10
this.store.find('list', {page_size:1, page_number:10});
Personally I think it's a bit hacky to go fudging the model names and namespace to make it supposedly fit your backend's url structure. It really depends on what you're attempting to do. If you want all the full features of CRUD using Ember-Data for this particular list of data, you're going to be hacking the end-point left and right. Whether or not Ember Data really helps you is questionable. If you are just reading data, I'd totally just fetch the data using jquery and sideload it into Ember Data.
var store = this.store;
$.getJSON('/api/rest/debtor/lists?page_size=1&page_number=10').then(function(json){
//fix payload up if necessary http://emberjs.com/api/data/classes/DS.Store.html#method_pushPayload
store.pushPayload('type', json);
}).then(function(){
return store.all('type'); // or store.filter('type') if you want to filter what is returned to the model hook
});
pushPayload docs

Where to save detailed user session information for EmberJS app?

I am building my first EmberJS app, and am still trying to wrap my head around the best practices & conventions. I'm using ember-data to talk to a RESTful API, and have ember-auth working well enough to log in and save a user's ID & OAuth2 access token. However, I'd now like to maintain additional user information (e.g. name, email, etc) for use in the navbar and in various other areas of the app.
To do this, I am thinking it would be helpful to have a User object (model) that is read from a separate endpoint (e.g. /users/<id>). Since this info would be needed throughout the app, I'm inclined to store it on the ApplicationController, somewhat like this example from Ember's docs:
App.ApplicationController = Ember.Controller.extend({
// the initial value of the `search` property
search: '',
query: function() {
// the current value of the text field
var query = this.get('search');
this.transitionToRoute('search', { query: query });
}
});
However, my user object wouldn't quite be an action like query or a property like search, so I'm not sure this example applies.
I think I'll eventually want to call something like:
this.get('store').find('user', App.Auth.get('userId'));
but I'm just not sure where in the app that would go.
Main question: is the ApplicationController the right place for this information per Ember conventions, and if so, what might the code look like to retrieve it from the REST API?
Appreciate any thoughts to put me on the right track.
The general approach that I've taken before is to store the currently logged in user as App.CurrentUser. Then you can use it in any template. Once I've pulled the User object I call Ember.set('App.CurrentUser',user) to store it, and then Ember.get('App.CurrentUser') to retrieve it in other routes or controllers.
Here's a short jsbin with the general idea : http://jsbin.com/ucanam/994/edit