# Deleting associated hasMany records in a nested route

**URL:** <https://discuss.emberjs.com/t/deleting-associated-hasmany-records-in-a-nested-route/12979>\
**Category:** Design\
**Created:** [May 15, 2017, 11:56pm UTC](https://discuss.emberjs.com/t/deleting-associated-hasmany-records-in-a-nested-route/12979 "2017-05-15T23:56:20Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![munderwood](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/munderwood/32/13020_2.png) [@munderwood](https://discuss.emberjs.com/u/munderwood)\
**Post date:** [May 15, 2017, 11:56pm UTC](https://discuss.emberjs.com/t/deleting-associated-hasmany-records-in-a-nested-route/12979/1 "2017-05-15T23:56:20Z")

</div>

I’m trying to figure out the best Ember 2 way to display a list of associated records in a nested route for a single given record of a different type, and to be able to modify the list (by adding or deleting associated records) so that the template updates to show the latest list. For now I’m just concentrating on deleting associated records.

As a concrete example of what I have so far, say an author has many books and they are displayed in a nested route, `/authors/:author_id/books`:

```
// routes/authors/books.js
import Ember from 'ember'

export default Ember.route.extend({
  
  model () {
    const author = this.modelFor('authors')
    return Ember.get(author, 'books').sortBy('title')
  },
  
  actions: {
    deleteBook (book_id) {
      const author = this.modelFor('authors')
      const filteredBooks = Ember.get(author, 'books').filter(
        book => Ember.get(book, 'id') === book_id
      )
      if (filteredBooks.length < 1) { return }

      // At this point just delete locally in client app.
      filteredBooks[0].deleteRecord()
      console.log(Ember.get(filteredBooks[0], 'isDeleted')) // true
    }
  }
  
}

```

An author’s books are displayed by a template:

```
// templates/authors/books.hbs
<ul>
  {{#each model as |book|}}
    <li>
      <button {{action 'deleteBook' book.id}}>🗑</button>
      {{book.title}}
    </li>
  {{/each}}
</ul>

```

This works as far as displaying the initial list of books in the template, finding the correct book in the `deleteBook` method, and calling `deleteRecord` on it. Afterward, the `isDeleted` proeprty of the book returns true.

However, the list of books rendered in the template doesn’t change, and repeated clicks on the delete button for a single book continue to find and re-“delete” the book on every click. Can anyone shed any light on why this isn’t working as I expect? Is this a decent approach, or is there a different way I should be using Ember to accomplish the desired outcome?

---

<div class="post-metadata">

**Author:** ![dknutsen](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/dknutsen/32/16471_2.png) [@dknutsen](https://discuss.emberjs.com/u/dknutsen)\
**Post date:** [May 16, 2017, 12:17am UTC](https://discuss.emberjs.com/t/deleting-associated-hasmany-records-in-a-nested-route/12979/2 "2017-05-16T00:17:33Z")

</div>

Hey @munderwood,

I would first recommend that you handle that action in your controller instead of your route. Then you don’t need to use ‘modelFor’ and can just reference ‘model’ directly. I like to think of the route as what fetches the data and handles any transition and associated state, and the controller handles user interaction and holds the GUi state, more or less.

Second, I think part of the problem may be that you’re calling deleteRecord and you’re never persisting that change via `<model>.save()`. Alternatively you can use `destroyRecord` instead of `deleteRecord`, which is essentially just a shortcut to do a `deleteRecord` and a `save` at the same time. See [the guide](https://guides.emberjs.com/v2.13.0/models/creating-updating-and-deleting-records/) for more details.

EDIT: a third thing you could do is actually pass the entire book in your action (instead of ‘book.id’) and just delete it that way instead of having to do a filter. Also, instead of doing filter you could use some of the Ember helpers and say:

```auto
    filteredBooks = Ember.get(author, 'books').findBy('id', book_id);

```

It’s a little cleaner.

---

<div class="post-metadata">

**Author:** ![munderwood](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/munderwood/32/13020_2.png) [@munderwood](https://discuss.emberjs.com/u/munderwood)\
**Post date:** [May 16, 2017, 4:10pm UTC](https://discuss.emberjs.com/t/deleting-associated-hasmany-records-in-a-nested-route/12979/3 "2017-05-16T16:10:10Z")

</div>

Hi @dknutsen,

Thanks for the reply and feedback. I’ve moved the action to the controller and changed it to accept the `book` instance instead of the `book_id`. The code is definitely a lot cleaner now!

Unfortunately, I don’t think you addressed the root issue that I’m having. As I pointed out in a comment on the call to `deleteRecord` in the sample code, my goal here is just to remove the associated record locally in the client.

I understand the difference between `deleteRecord` and `destroyRecord`, but I’m trying to let the user add and delete as many `book`s as they want in the browser, and then either confirm the changes and save the new set in a single request to the server, or cancel the changes and leave the state on the server unchanged.

What I don’t understand is why deleting the record in the client doesn’t remove it from the list rendered by the template in the `#each model` block, regardless of the state on the server. Do changes to the state of the store not get propagated to the `model` on the route?

---

<div class="post-metadata">

**Author:** ![munderwood](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/munderwood/32/13020_2.png) [@munderwood](https://discuss.emberjs.com/u/munderwood)\
**Post date:** [May 16, 2017, 5:14pm UTC](https://discuss.emberjs.com/t/deleting-associated-hasmany-records-in-a-nested-route/12979/4 "2017-05-16T17:14:43Z")

</div>

I also just edited the calls to `modelFor` in the sample code of the question.

They are now getting the model of the _parent_ route (`books`) first via `modelFor`, and then returning the child records of the `hasMany` association (`authors`) as the `model` for the nested route, `/books/:book_id/authors`. Now that I’ve corrected my error, do you still think that I should be able to ditch the `modelFor` call and instead reference `model` directly? If so, what would that look like?

---

<div class="post-metadata">

**Author:** ![dknutsen](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/dknutsen/32/16471_2.png) [@dknutsen](https://discuss.emberjs.com/u/dknutsen)\
**Post date:** [May 16, 2017, 6:01pm UTC](https://discuss.emberjs.com/t/deleting-associated-hasmany-records-in-a-nested-route/12979/5 "2017-05-16T18:01:22Z")

</div>

@munderwood sorry I misunderstood that the first time, my bad! I think what you’re seeing is an intentional design decision. If you do a “local” deleteRecord, the record is still in the store and still in the backend, it’s just been flagged for removal on the next save. So I think it makes sense to keep it in the live record array. This is somewhat speculative on my part, but I’m guessing the reason it works this way is so you could do a local delete and when the ‘isDeleted’ flag is set to true on the record either grey it out or hide it, depending on your use case. Then when you persist that delete to the backend the recordArray will update. So, for your use case, if you want to confirm the changes as you described, I would simply add an if/unless block to only draw the component if ‘isDeleted’ is false.

In terms of your most recent question, if I’m understanding what you’re asking correctly, I would do something along these lines:

```auto
// templates/authors/books.hbs
<ul>
  {{#each model as |book|}}
    {{#unless book.isDeleted}}
    <li>
      <button {{action 'deleteBook' book}}>🗑</button>
      {{book.title}}
    </li>
    {{/unless}}
  {{/each}}
</ul>

```

```auto
// routes/authors/books.js
import Ember from 'ember'

export default Ember.route.extend({
  
  model () {
    const author = this.modelFor('authors')
    return Ember.get(author, 'books').sortBy('title')
  },  
}

```

```auto
// controllers/authors/books.js
import Ember from 'ember';
export default Ember.Controller.extend({
  actions: {
    deleteBook (book) {
      if (!book) { return }
      // At this point just delete locally in client app.
      book.deleteRecord()
      console.log(Ember.get(book, 'isDeleted')) // true
    }
  }
};

```

EDIT: if for whatever reason you must also do a ‘save’ on the parent model (I can’t remember if you have to or not… I don’t think you do but maybe…) you could just pass the full parent model to the child:

```auto
// templates/authors/books.hbs
<ul>
  {{#each sortedBooks as |book|}}
    {{#unless book.isDeleted}}
    <li>
      <button {{action 'deleteBook' book}}>🗑</button>
      {{book.title}}
    </li>
    {{/unless}}
  {{/each}}
</ul>

```

```auto
// routes/authors/books.js
import Ember from 'ember'

export default Ember.route.extend({
  
  model () {
    return this.modelFor('authors')
  },  
}

```

```auto
// controllers/authors/books.js
import Ember from 'ember';
export default Ember.Controller.extend({
  // add a couple CPs for convenience
  author: Ember.computed('model', function(){
    return this.get('model');
  },
  books: Ember.computed('model.books', function(){
    return this.get('model.books');
  },
  // this will sort the books
  sortedBooks: Ember.computed.sort('books', 'bookSortDesc'),
  bookSortDesc: ['title'],
  actions: {
    deleteBook (book) {
      if (!book) { return }
      // At this point just delete locally in client app.
      book.deleteRecord()
      console.log(Ember.get(book, 'isDeleted')) // true
    }
  }
};

```

---

<div class="post-metadata">

**Author:** ![munderwood](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/munderwood/32/13020_2.png) [@munderwood](https://discuss.emberjs.com/u/munderwood)\
**Post date:** [May 16, 2017, 6:48pm UTC](https://discuss.emberjs.com/t/deleting-associated-hasmany-records-in-a-nested-route/12979/6 "2017-05-16T18:48:27Z")

</div>

Excellent, thank you! In particular the simple `#unless` block solved the one very specific aspect of the problem that originally prompted me to post the question. But it’s so helpful to see the complete worked example you gave, and to learn _why_ I should use that as the solution. Now that you point it out, it does of course make sense that the deleted (but not destroyed) record has to still be accessible somehow, and there’s not really any better place than in the same array of records, with the `isDeleted` flag set.

---

<div class="post-metadata">

**Author:** ![dknutsen](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/dknutsen/32/16471_2.png) [@dknutsen](https://discuss.emberjs.com/u/dknutsen)\
**Post date:** [May 16, 2017, 7:10pm UTC](https://discuss.emberjs.com/t/deleting-associated-hasmany-records-in-a-nested-route/12979/7 "2017-05-16T19:10:25Z")

</div>

Awesome! Glad that worked. There’s all kinds of cool stuff you can do with Ember that can make your code shorter and faster and well-structured. I feel like I’m still learning new techniques and features all the time. In case you’re interested, here are a couple really cool resources I’ve run across recently:

- This is a great document with lots of good idiomatic examples: [GitHub - poteto/ember-workshop: This is a workshop designed for intermediate developers who have worked on at least one large Ember app. The goal is to teach functional programming basics and to be able to use these ideas in your app.](https://github.com/poteto/ember-workshop)
- Ember Styleguide: a guide for writing Ember code with commonly accepted “good” style: [https://github.com/dockyard/styleguides/blob/master/engineering/ember.md](https://github.com/dockyard/styleguides/blob/master/engineering/ember.md)
