application level component property change - ember.js

I need to change the layout componet value from page level template.
like in picture x.hbs may vary according to route.each spesific route may have add to cart button and when add to cart button click the layout component price should be updated.
how to do something like this in emberjs way?

To manage global state you should use an service.
However for you use-case I would just rely on the store-Service provided by ember-data. You probably should create a model for your shopping-cart-items. Then you can do something like store.findAll('shopping-cart-item') in your application routes model hook. In the application controller you can get the sum with a simple Computed Property.
Now if you add items to your cart, ember-data will keep everything in sync.
Maybe checkout this twiddle for demonstration.

Related

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.

What is the correct way to use Ember.Select with Ember-CLI

I am trying to get Ember.Select to work and am almost there. I have put up an example: http://exmer.com/selecttest/pages
To see my problem click on some Recent Pages and click edit. The select is not fetching the model via contentBinding="controllers.modelnames". If you click to modelnames route and edit some Recent Pages again it works correct because now we fetched the modelnames. I can perhaps fetch the modelnames from the page controller myself but this seems to me more like a hack.
The source is on https://github.com/broerse/ember-select-test (it runs without CouchDB)
So my question is: What is the correct way to use Ember.Select with Ember-CLI
Understanding the ember workflow is really important here. When you navigate to a URL Ember parses the URL and maps it to your router. At that point Ember knows it needs to fetch the models from each resource/route that are part of the URL. Once it's fetched all of those models it decorates them with the associated controllers. This right here describes where your issue is. Just using a controller doesn't cause a model to be fetched. You're using needs on a controller which isn't a parent/ancestor in your router, so you aren't guaranteed it will be populated. You'll need to manually fetch the model and store it on the other controller, or fetch the model and store it on the current controller in order to make sure it exists when you visit that route.
Ember select works the same everywhere (ember cli or not), no matter if it's ember data or some other library or just pojos.
hbs
{{view 'select' content=model
optionValuePath='content.id'
optionLabelPath='content.name'
selection=selectedModel}}
That would mean your model has an id attribute and a name attribute. The model would be populated from the route, if it's a secondary model, you can use this.modelFor in the route and set it to a different attribute on the controller in setupController on the route.
The issues with Ember select is performance and that it's not a component.

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"
});

User flow assistance

I'm working on an Ember.js application that contains several models with dependencies. For example, when setting up a model for Client I include the attribute portfolios : DS.hasMany('Portfolio')
When a user enters the app, they are presented an option to immediately add a new portfolio at the route portfolio.add where among other form fields they are presented a drop down to select the client for whom they are creating the portfolio, as well as an option to create a new client via {{#link-to client.add}}. This is NOT the only way a user could get to the route client.add
I'd like for Ember to remember that the user got to the client.add route via portfolio.add, change the text of the submit button to indicate that they will return to portfolio.add after saving, and to transition back to portfolio.add after the promise returns successfully where it will auto select the newly created client in the drop down.
So far I've thought I'd use this answer: How can I get My previous route? to check the previous route, and possibly create a similar mixin for storing a reference to the created client record.
It's a hack, and I'd rather pass related objects/properties directly. Is there a better way?
I ended up advancing my Ember build to Canary and including Ember.FEATURES["query-params"] = true;
I then added a routedFrom parameter when shifting into a view that would need to route back on completion and in the original route's model I added this.transitionTo('originalroute',{routedFrom:null}); to clear the routedFrom parameter.

Why does ember use the same controller instance on separate visits to a route?

Problem:
I have a conceptual problem with re-using an old controller instance when the user re-enters the route. In many examples, the controller stores the state of user interaction in instance variables. When the user re-enters the controller those should be reset, but there is no clear mechanism for doing so.
So, there must be a good reason to use a single controller instance. What is it?
How I arrived at this issue:
I ran into a bug in out Ember app, where the controller keeps local state that got out of sync based on the user actions elsewhere. The controller maintains a state whether the user is editing the "name" of a "case". When the controller is instantiated, that is set to "true", but when the user cancels, it's set to "false". Then the user goes away to a different route and comes back to the same route. I get the same controller instance that already has "false" for editing the name. I would expect to have "true" instead.
Ember v.s. Rails:
I'm coming from Rails perspective where controller is instantiated for every request. There is no shared controller state between requests. All instance variables are local to the request, so they can be used safely.
Back to the question:
Why does ember use the same controller instance on separate visits to a route?
The role of a controller in ember and in rails are very different. In rails, as you know, the controller is used as a conduit for the request to prepare the data for presentation. If you consider the use case in ember, this is a role that is primarily played by the router.
In your example you mention that the edit state has gotten out of sync. You can solve this problem in a variety of ways, for example you could move the edit state to the model, so instead of isEditing, you'd call model.isEditing (or just isEditing if you are using an ObjectController). Another option would be to reset the state of the controller when entering the route.
Another example which should illustrate this difference is a save button on a form. Initially you might think "Oh, I'm going to put a save action on my controller". This is logical, when you're thinking like a rails developer, but saving a model is the responsibility of the router (especially if it results in changing the current route as this is something that's intentionally hard to do from a controller).
In ember the role of a controller is as a conduit between the model and the view. The fact that controller instances are re-used is a little confusing, but really isn't that important. When you change or return to a route the model/context of the controller is different, and that is where the state of the view should live... in the model.
Although controllers are usually singleton, when you use {{render}} with a specified model you will get a newly instantiated controller. See rc2 release notes under "Using Render with Multiple Models". I'm new to Ember and this difference confused the heck out of me.
Using a singleton controller when trying to keep per-model-instance user interaction state seems tricky. As jonnii said, you can put the state on the model, and that works but it cruds up the data model. The other thing I have tried is to put a map in the controller (keyed by model, value is an object of user interaction state) but this seems like a clumsy reimplementation of something I'd expect the framework to provide. Still working on this...