Skip to content

03.0.0 Edit a Model

Tim van den Eijnden edited this page Nov 4, 2015 · 9 revisions

What you will learn

  • Add behavior to the Edit button
  • Change state of detail page
  • Edit the product
  • Make the buttons work
  • Rollback changes on url change
  • Bonus: Make use of the hasDirtyAttributes state

Before you start

See the installation instructions. Use tag 3.0.0.

For the time being we stub all requests by using Mirage. This tag already updated frontend/app/mirage/config.js to stub the PATCH request when a model is updated.

Add behavior to the Edit button

  • Open frontend/app/templates/products/show.hbs.
  • Change the markup for the Edit button and call the (yet to define) toggleEditing action when you click it:
<button {{action 'toggleEditing'}} type='button' class='edit'>Edit</button>
  • In the app, select a product and click the Edit button.
  • Inspect the error shown in the Console tab in the browser. Ember is missing the toggleEditing action, so let's create this. Ember first looks for this action on the ProductsShowController. Since we didn't need any special behavior for this controller until now, it's auto-generated.
  • In the terminal, enter ember g controller products/show.
  • Open frontend/app/controllers/products/show.js and add toggleEditing:
export default Ember.Controller.extend({
  actions: {
    toggleEditing() {
      alert('Hello from toggleEditing');
    }
  }
});
  • In the app, select a product and click the Edit button again.

Change state of detail page

The action should change the isEditing state of the controller so the template can show the proper markup accordingly.

  • Open frontend/app/controllers/products/show.js and update the code:
export default Ember.Controller.extend({
  isEditing: false,
  actions: {
    toggleEditing() {
      this.toggleProperty('isEditing');
    }
  }
});
  • In the app, select a product and click the Edit button again and use the Ember Inspector to see how the isEditing property changes.
  • Open frontend/app/templates/products/show.hbs.
  • Wrap the content for the page in a conditional:
{{#unless isEditing}}
  ...
{{/unless}}
  • In the app, select a product and click the Edit button again. This sets isEditing to true, which hides the product detail (notice that the template is still rendered, though). Selecting another product will not bring back the product detail; the controller's property isEditing is still true so the template still hides the details.
  • You'll reset the isEditing when you change the URL.
  • Open frontend/app/routes/products/show.js and update the code:
export default Ember.Route.extend({
  actions: {
    willTransition() {
      this.controller.set('isEditing', false);
    }
  }
});
  • In the app, select a product and click the Edit button again and then select a different product.

Edit the product

  • Open frontend/app/templates/products/show.hbs.
  • Scroll down to {{/unless}} and add {{else}} and an empty line above it:
{{#unless}}
  ...
{{else}}
  
{{/unless}}

Make the buttons work

  • Open frontend/app/templates/products/show.hbs.
  • Change the markup for the Cancel button and call the toggleEditing action when you click it:
<button {{action 'toggleEditing'}} type='button' class='cancel'>Cancel</button>
  • Open frontend/app/controllers/products/show.js.
  • Add code to rollback the changes:
toggleEditing() {
  this.toggleProperty('isEditing');
  this.model.rollbackAttributes();
}
  • Change the markup for form tag and call the yet to be defined submit action when it is submitted:
<form {{action 'submit' on='submit'}} role='form' class='well'>
  ...
</form>
  • In the app, edit a product and submit the form.
  • Inspect the error shown in the Console tab in the browser. Ember is missing the submit action, so let's create this.
  • Open frontend/app/controllers/products/show.js and add toggleEditing:
actions: {
  toggleEditing() {
    ...
  },
  submit() {
    this.model.save().then(() => {
      this.set('isEditing', false);
    });
  }
}
  • In the app, edit a product and submit the form again.

Rollback changes on url change

When you make changes to a product and then change the url (e.g. click another product), the changes remain. Let's fix that.

  • Open frontend/app/routes/products/show.js and update the code:
willTransition() {
  var product = this.currentModel;

  if (product.get('hasDirtyAttributes')) {
    product.rollbackAttributes();
  }
  this.controller.set('isEditing', false);
}

Bonus: Make use of the hasDirtyAttributes state

  • Open frontend/app/templates/products/show.hbs.
  • Bind the class attribute of the submit button to the model's hasDirtyAttributes state. When the model is dirty, add the class disabled to the button. Regardless the model's state, update is always used as className:
<button type='submit' class='update {{unless model.hasDirtyAttributes 'disabled'}}'>Update</button>
  • Open frontend/app/templates/products.hbs.
  • Update the div tag wrapped by <div class='product'> as follows:
<div class='thumbnail {{if product.hasDirtyAttributes 'is-dirty'}}'>
  ...
</div>