When should I be using router actions as opposed to using controller actions? I know they both serve different purposes but not sure why.
Thanks.
No, technically they serve the same purpose, it's more a matter of where you want actions to be handled/scoped.
Actions are bubbled in a very specific fashion. From the dom they hit the associated controller, then that controller's associated route, then up the route tree (defined by the router mapping). http://emberjs.com/guides/templates/actions/#toc_action-bubbling
So if you think the action will never need to be used past the controller (aka you won't ever want to use it from some child route) then the controller is appropriate, if you think maybe a child route will want to trigger the parent's action then inside the route it goes.
Related
TL;DR
Embers components are just smart HTML-Templates. Why they don't fetch their data for themselves like Angular? And how I can share route models over more URLs/pages. It seems that I have to know wich components are placed on which URL and I have to make them the data available over the route models. Why is this part not in the component?
I learn at the moment Ember.js. I try at least.
At the moment I have a strong problem to understand why Ember.js acts like it does. Please correct me if I am wrong at some statements. I am an Ember.js beginner. So maybe its not right what I point out here.
Lets say we have a Request on / then Ember tries to find a route model in app/routes/index.js this file contains the code which data I want to fetch from the backend. Next Ember will render app/templates/index.hbs in this file I have a component called car-list.
As far no problems but let us have a closer look. For me it feels very weird that I have to fetch at first the data by myself, why the component doesn't do this on its own? Next problem is then how can I share the model fetch logic between more routes? Maybe I want to place my component on many URLs/pages/routes then I have to copy the route model logic?
In my opinion, the component should fetch the data by itself, that you can easily insert the component on other pages without copy the whole route model fetch logic.
So I have to know wich components are placed on which URL and I have to make them the data available over the route models. Why is this part not in the component?
So maybe I am just not good enough with Ember and I just overlook something?
Components are very flexible. Components have made to be reusable. For example you can create a table component and use for cars, ships, etc.
So for reusability it's better you separate model providing from component.
But if you want to make a component which is for current project and need to fetch its data itself, you can fetch data in the component.
In some scenarios you might want to fetch data in routes. For example in your page you have multiple components and every component needs a projection of data model which fetched in route.
So it depends on your requirements, maybe you need to fetch data in component or in route or even both (mixed)
Components certainly can load their own data, and in many cases that is appropriate. But allowing the route to load the data has several important benefits that you get "for free" if you stick to that pattern:
your application's URL will always reflect the state of the data. You don't have to remember to synchronize it (in both directions -- changes to URL should change the data, and changing the data should change the URL).
you can write your templates knowing that they won't render until the data is present, allowing Ember to handle the asynchrony for you. This results in cleaner, simpler templates.
you get Ember's built-in error handling for when the data fails to load.
A username component that appears on many pages typically belongs fairly high in the route hierarchy anyway, like in the application template, where it's easy to load & render it once from a single place and have it remain visible on every child route.
But if you do need to use a component in many places and its data should be self-contained, it's fine to let it do its own loading. In that case you can either rely on Ember Data's store to give you cached responses (so you only trigger a network request the first time) or write a Service that handles some persistent state for your component.
Using Ember I have a parent route with two nested child routes each child with a dynamic segment. The parent route does a calculation on its model to determine the “default” value of the dynamic segment for its child. Then the first child does the same for its own child route.
Everything is working well. However, what I’m seeing is that the adapters for the parent route and first (outer) child are being called twice. This causes a performance hit.
At each point where I do the calculation for the dynamic segment, I then do a “transitionTo” with the calculated value to load the child route. This is happening in the afterModel hook. I’m guessing that’s where the problem lives.
I’m able to prevent the second call to the adapter by checking the store to see if it’s already cached by that id. Is this what I should do or is this a hack required only because I’m misusing transitionTo in afterModel?
i'm very confuse about how ember controller works.
I'm starting with ember and ember-cli now, and i would like to understand more about how controller works.
If i have an nested route called new, inside a events resource, i should i have:
models/event
routes/events/new
templates/events/new
What about controllers?? I just work one simple controller, or should i use controllers/events/new too?
There isn't any generator command that will create every resource for me? I need call one by one?
Thanks.
What about controllers?? I just work one simple controller, or should i use controllers/events/new too?
This mainly depends on what is your controller needs to do. If it's only the essential stuff the controller does anyways, Ember will create that controller under the hood for you and automatically bubble actions up to its parent controller.
No better place than Ember guides to read what a controller is used for:
The simplest definition is:
Controllers allow you to decorate your models with display logic.
This means that you basically use them as the main communication layer between your route and your template. Essentially, you model comes from your route, through your controller and into your template. Actions happening in the template go up to the controller and then to the route. Therefore, controller is essentially the middle layer where you user your model (and other data) to control what is shown to the user, control what a user can do, control where can they navigate etc.
However, be aware of the plan for the future:
Controllers are very much like components, so much so that in future versions of Ember, controllers will be replaced entirely with components. At the moment, components cannot be routed to, but when this changes, it will be recommended to replace all controllers with components.
This means, that right now, controller responsibility is limited to two things:
Maintaining application state based on the current route
Handling or bubbling user actions that pass through the controller layer when moving from a component to a route.
All actions triggered on a template are first looked up on the controller, if it is not handled or bubbled (by return true) in the controller, they are looked up on the route.
Therefore, controllers for your /events or events/new routes aren't necessary at all, only if you want to handle things happening on those routes right away (in a smaller scope) instead of allowing everything to bubble up to the ApplicationController.
There isn't any generator command that will create every resource for me? I need call one by one?
Yes. Since, if you don't specifically create a controller, Ember just generates one for you behind the scenes. You need to specify where you want to handle things yourself.
You should visit the link I gave above (or here it is again) to the Ember guides that have many more examples in much more detail.
when i tell my angularjs app to navigate backwards
$window.history.back();
i see that the previous view's controller is being reused. is there a way to force angularjs to instantiate a new controller?
i am using a ngView element on the page and populating it with templates. perhaps there is a way to dictate to the router that a new controller should be instantiated each time.
(why is stackoverflow insisting on more words before i can submit my questions?....)
I think you should be investigating the $templateCache. I believe in many cases, Angular does instantiate a "new" controller on this event, but your template cache injects the data/state of the view when you use the history service.
Really, it all depends on scope... if your forward progress (app interaction) keeps your state and view within or underneath (as a child of) the same scope, the controller will never be destroyed, however if you leave the scope, it should clean up. (this is actually javascript, and Angular wraps that behavior with $scope). The $templateCache either way will rebuild the state, including data models within your view's assigned controller.
You would have to go about this by intercepting the history event taken, search the $cacheFactory or $templateCache for the key/value pair matching the view in question, then run:
$templateCache.remove('keystring');
prior to allowing the history event to execute. via the $cacheFactory, you can use $templateCache.get() to return information about the views you have cached.
Check out:
- http://docs.angularjs.org/api/ng/service/$cacheFactory
When using {{render "modelHandler" model}} the corresponding controller's model function is never called.
Reproduced here: http://jsbin.com/EVoXAceP/3/edit
I'm 90% sure this is a bug. I'm posting this here before I post to github in case there is something obvious I've missed or "I'm doing it wrong." In either case, if you could kindly point me in the right direction.
Use Case (Why I need this to work in the first place).
I'm using {{render}} to include an AddressAdd template, for which I need to extend the model to include a list of states as well as the default state. While I could load the states onto the parent model (say a property or a contact card), since many views include an AddressAdd I'd like to avoid having to manually add the information for the drop down each time.
So if you also happen to know a better way of implementing this besides {{render}} and the controller's model hook, please let me know!
It isn't a bug, the model hook is only fired when you visit the url associated with that route, and it lives on the route, not on a controller. Additionally, if your controller has a model on it it should be an ObjectController (unless it's an array, then it's an ArrayController).
http://jsbin.com/EVoXAceP/13/edit
When you call render you are saying you want to render a particular template using a particular context.
I would create a route underneath the route you're in and use a link-to without a model, which will cause the model hook to fire.
In your application template
{{ render 'foo' bar }}
shouldn't you have a bar property in the ApplicationController?
App.ApplicationController = Ember.Controller.extend({
bar: {isBar: 'yup'}
});