EmberJS "detail" page fetches the model automatically - is this normal? - ember.js

Long time reader - first time questioner here.
I am developing a medium sized application in EmberJS which is a framework that I have been using for a while.
Today I have realised that it fetches model data from the server without me writing any code.
I have a main route called "students". Then there is a "list" sub route where the model() function of this route calls the store to fetch all the students and lists them on a table.
On each row of this table I link to another sub route called "detail" where it accepts the ID of each student as an argument. However inside the route.js file for this route there is no model() function querying any information about the specific student from the server.
Ember does this automatically somehow as I can see the appropriate network request being made using chrome dev tools.
How is this happening and is it normal?
Thank you in advance.

The Ember router will automatically load a model if it detects a dynamic segment that ends in _id.
Ember follows the convention of :model-name_id for two reasons. The first reason is that Routes know how to fetch the right model by default, if you follow the convention
You mentioned that your api route is /api/student/details/:student_id and I would expect that your ember route is fairly similar.
It detected _id, and called store.find('student', params.student_id) automatically for you when you navigated to that route.
This is completely normal, and is one of the ways Ember encourages you to follow convention - If you do, you don't have to create as much boilerplate.
If you want to avoid the second request, possibly because the list route pulls all relevant data, you can pass the student model instead of the student id.

Related

Url not updating when new model is saved

router.js
this.route('claim', function() {
this.route('new');
this.route('edit', { path: '/:claim_id' });
});
claim.new -> redirect to claim.edit with an empty model. this.transitionTo('claim.edit', model);
Initially, because the model is not saved we get: index.html#/claim/null
When we save the model, it continues to display as index.html#/claim/null instead of say index.html#/claim/87
Is there a way to force the url to refresh?
The only way to force the URL to refresh is to force the route/page to refresh. You can use the refresh method in your route to do that.
To understand why it doesn't update automatically, you have to understand how routes work and how Ember is separate from Ember Data (or any data persistence library).
First, you have to remember that Ember has no knowledge of Ember Data and the specifics of its object model. It just sees plain Ember objects. Ember Data models are more important than other models to you, but Ember isn't aware of that distinction.
Second, the routing in Ember is binding/observer aware. It doesn't watch for changes and update URL state accordingly. It calculates the URL once using the serializer hook, then it leaves it as that. It's not going to recalculate if your model changes in any way. It will only recalculate when it's refreshed.
Short story long, the part of your application that changes the ID of your model and the part that calculates the URL to use aren't aware of each other. You'll have to manually sync them up. Using the refresh method is probably easiest way to do that.
UPDATE: As Kitler pointed out, you can also transition to your route using the new model. It won't fire the model hook so it won't have to do any asynchronous work, but it will still update the URL.

Reuse ember controller for two routes, but pre populate part of model on one of the routes

Lets say we were modelling repositories in an app. We would want to be able to see all of our repo's at /repos/.
We can create a repo at /repos/create. In our model a repo has a owner (user), going down this route I would want my first form field in my create.hbs template to be selecting a user.
But it may also make sense to create a repo through viewing a user at /users/userId/repos, and then perhaps the route being /users/userId/repos/create. The difference here would be that the first field of my form would have the user pre populated.
I know that I can reuse the same controller by specifying this in my route:
controllerName: 'repos/create'
(what would the ember generate statement/ the place to put this route in my folder structure be, for this complex route?)
But how would I pass in the user to the repos/create controller?
The comment by #Artych provided the best way to do this currently, so to expand on this.
In the end I created a repo-create component that may or may not be passed a user object. The logic for handling what to pre-populate can then be set in the logic of the component itself.
After this is was simply a case of having a one line template at both /repos/create.hbs and /user/repos/create.hbs, with the component.
I then followed the approach of using my user as my model in the routes/user/repos/create.js route and passing it to the component in my template as
{{repo-create user=model}}
With this approach I avoided doing anything explicitly on controllers, and moving up to Ember 2.x will be alot less painful.

Ember CLI path based on server response

I'm developing a substantial ember app, using Ember CLI, and I'm struggling with a few aspects of it.
What I want to do is:
Show a dropdown list of options
When the user picks an option, post their choice to the backend
The response from the server contains data based on what the user picked in the dropdown. After getting the server response I want to transition to a new route where the path ends with one of the values returned by the server.
For example:
/path/to/dropdown -- shows the dropdown for the user to pick from, which is then POSTed to the backend. The backend responds with, amongst other data:
slug: <stringValue>
This then transitions to:
/path/to/slug -- where slug is <stringValue>
So far I've got 1 & 2 above working, but I can't figure out how to make step 3 work. I've tried using a serialize function in the /path/to/slug route and the /path/to/dropdown controller, but it always returns undefined.
The AJAX call to the server, based on the user's dropdown choice, happens in the /path/to/dropdown controller.
I've set up the router as:
this.route('options', { path : ':slug' });
Would be great if someone could point me in the right direction; I hope my example is clear enough but let me know if not.
Thanks.
To be honest I don't understand why do you use this.route('options', { path : ':slug' });. You just created the only route for all possible options (in fact, for all urls of form /anything), but that's not what you want.
I think your solution is this.transitionToRoute(url_string) which is available in any controller. Check the api example there. But before you should declare all that routes in the router and create operating files for them, of course.
If you don't want to create a route for each possible slug, so then your route is pretty excellent, but at least I'd consider to add one more path section. For example, this.route('options', { path : '/slugs/:slug' });.
After that you can run transitionTo and pass data (in any format) to it. The data will be assigned to the route model and you will be able to use it in the SlugRoute (and SlugController, if you didn't redefined the setupControler method) as a this.get('model') variable.
If you want to run transition from the view, firstly you need to obtain the controller and send a special command to it.

Django Rest/Ember How to connect to models

I am getting started with Ember, and Django Rest Framework and I can't seem to peice together how to connect a model so that Ember can use the data in that model and create a simple drop down box. I have one model that I am starting with that is as such:
id
name
security
status
All I want to achieve is allowing Ember to use the data in this model and create a dropdown like so.
<select id="model">
<option value="model.ID">model.Name</option>
</select>
Can anyone help me with this? I am complete new to Ember and Django Rest.
Without going into a ton of detail, I've created a mini example of what you're looking for
http://emberjs.jsbin.com/Ozimatuj/2/edit
You'll note that I'm using mockjax, so instead of hitting any real endpoint, it's all mocked. Additionally I'd recommend using a client side record management solution (such as ember-data or ember-model). That's another discussion though.
In the application route (which correlates with the root of your app) it hits the model hook (which should return the model associated with that route. I'm returning a POJO of the users. That model is being assigned as the content of the application controller (automatically generated). The the application template is being built, and it's being backed by the application controller. Inside the application template we create an instance of ember select, and we tell it that the content backing it is model (which is the model/content in the application controller). We also say, use bind the user model (you could do id) and the name to the value and the label respectively.
I then bound the value of the select to selectedPerson, so anytime the value changes, the selectedPerson updates, the template which talks about that person will update. Magic. Ember does the rest.
This is a really broad question, so if you have any other questions, please ask a specific question, and I'd really recommend going through the getting started guide, it's really short, but will give you a decent foundation of terminology and methodology of Ember. http://emberjs.com/guides/getting-started/
For Ember Data I'd do a quick read the of the transition document for ED 1.0 beta.
https://github.com/emberjs/data/blob/master/TRANSITION.md
DS.DjangoRESTSerializer = DS.RESTSerializer.extend();
DS.DjangoRESTAdapter = DS.RESTAdapter.extend({
defaultSerializer: "DS/djangoREST"
});

How to communicate data between controllers in Ember.js?

I am in the painfully slow process of learning Ember and find the guides and documentation severely limited when it comes to non-trivial examples.
To my question now.
Given the following router definition:
App.Router.map(function () {
this.resource('home', function() {
this.resource('weather', function() {
this.route('site', {path: '/:weather_site'});
});
});
When the user enters the home.weather.index route the model hook executes and fetches all weather information from the server. When the user then enters home.weather.some_site the model hook of the new route would bring weather data for that particular site from the server. How can this redundancy be prevented? In other words, how can controllers communicate data to each other? Should I use the setupController hook in each Route to achieve this or are there better ways?
Are there any good resources to help me understand the data flow in and out of Ember? Are there any good resources to help me learn Ember faster than digging into the source?
How can this redundancy be prevented?
It's not clear if/how/why the model hook for home/weather/index would fetch all weather information from the server. If that's desired behavior, then totally agreed there is no reason to fetch the same data when user enters home/weather/site.
If you are using ember-data there should be no redundancy since:
when user visits home/weather/index App.Site.find() fetches all weather data
when they visit home/weather/site App.Site.find(weather_site) returns site from cache and does not make a new request to the server
if user visits home/weather/site directly (or refreshes browser) then App.Site.find(weather_site) will call server and fetch just data for that site.
So unless there is something I'm missing there is no redundancy to prevent.
In other words, how can controllers communicate data to each other?
Seems unnecessary, but since you ask: Controllers communicate with one another via bindings. You declare a dependency from one controller to another via the controller's needs property, then Ember inject's a that dependency automatically. See the ember guide dependencies-between-controllers for more on how this works.
Should I use the setupController hook in each Route to achieve this or are there better ways?
That shouldn't be necessary in this case.
Are there any good resources to help me understand the data flow in and out of Ember?
Not clear what you mean by data flow. Best guess is that you'd learn a lot from Luke Melia's gothamjs presentation
Are there any good resources to help me learn Ember faster than digging into the source?
Reading the source is always a good option, but there are many other resources. I recommend checking out embercasts and ember weekly