How to edit record in ember.js


#1

I am very new to ember.js and also to this MVC thing. I am returning hard coded model from route. I want to edit records by click on edit button. I am calling an action from controller. How to return data from here and how to bind this in hbs.


#2

@Syash could you be a little more specific and maybe post some of your code?

How to return data from here

What is “here”?

and how to bind this in hbs

And what is “this”?


#3

Sorry if it was clear. Lets make it more clear. Suppose I have a view which lists all users subscribed to my application and it has an edit button against each record to update details of that user. When I click on edit i want to open a window(it may be a popup or a side panel) to edit the details in same view. How to achieve this with ember.js.


#4

For simplicity I’d do it in a side pane/area. Popup or modals are a little weirder. You’ll probably want to use nested routes. A good rule of thumb is anytime you want to nest views you’ll want nested routes, and in this case you’ll have an index view which then renders the ‘details’ view into an outlet. Here is one of the tutorials that goes into detail, but basically your router should look something like this:

Router.map(function() {
  ...
  this.route('users', function() {
    this.route('detail', { path: '/:user_id' });
  });
});

This is a pretty cool tool for playing around with your route structure. So you essentially have two routes here: users and users.detail. You can generate these automatically (even the nested stuff) using the ember cli generators, that part should be pretty well documented. The users route is the parent route and that should fetch and render the list of users. It should also render an {{outlet}} which is where the nested template will be rendered. The users.detail route should take the id given to it via the URL dynamic segment and use it to look up the user for the ‘detail’ view.

Now you’ll want to define your routes. The users route (<project root>/app/routes/users.js) should look something like this:

export default Ember.Route.extend({
  model(params) {
    return this.get('store').findAll('user');
  }
});

This tells Ember Data that you want all users in your backend.

The users.detail route (<project root>/app/routes/users/detail.js) should look something like this:

export default Ember.Route.extend({
  model(params) {
    return this.get('store').findRecord('user', params.user_id);
  }
});

Which tells Ember Data that you want to fetch a single user record, by id, and the id us user_id from the dynamic segment in the URL which gets passed in as part of the params argument.

So now it’s time for the templates. The template files should be in the exact same relative locations as their respective routes, but in /app/templates instead of /app/routes. The key points here are that in the parent users template you want to render the list of users somehow (could be ul, table, etc) using the {{#each model as |user|}} helper. Each of these items should probably use the {{#link-to 'users.detail' user.id}} helper. So you’d end up with something like this:

{{#each model as |user|}}
  <li> {{!-- or td or whatever you want to use --}}
  {{#link-to 'users.detail' user.id}}{{user.name}}{{/link-to}}
  </li>
{{/each}}

This is essentially saying “for every user in my model, render a link to the child route, pass the child route id, and for the link text render the actual user name”. Somewhere (probably below) that you’ll want to make sure you include an {{outlet}} so Ember knows where to render the child view.

Then in the /app/templates/users/detail.hbs template you’ll want to render the user details in a table or form or however you want to do it. Since the user data is in your model, each field will be available from {{model.name}} etc. If you want to refer to them as {{user.name}} instead you could add an alias on your controller with user: Ember.computed.alias('model').

Anyway for starters you’ll probably want to use the two way bound helpers like {{input}} and bind directly to the model properties. Then when you edit these fields it will edit the model directly, making the model “dirty”. To save a dirty model you’ll probably just want a button in your form that has an action called “saveModel” or something. The action (on your controller to start with) should simply do this.get('model').save();. That will persist the “dirty” edits to the backend.

Then you could refactor your users.detail template to a component, maybe use one way DDAU bindings on your editing fields, etc. But all that in time. Obviously if you have any more specific questions feel free to ask on this board or in the slack community, but I would also make sure you read over the tutorials and other guides. They can be a little anemic on some points but they should help you a lot with the fundamentals.