Enter Your Email Address to Watch This Lesson

Your link to unlock this lesson will be sent to this email address.

Unlock this lesson and all 959 of the free egghead.io lessons, plus get Angular 2 content delivered directly to your inbox!



Existing egghead members will not see this. Sign in.

Refactoring mutations to enforce immutable data in Angular 2

4:16 Angular 2 lesson by

When a Todo property updates, you still must create a new Array of Todos and assign a new reference. This lesson walks you through refactoring from the current approach to the immutable approach.

Get the Code Now
click to level up

egghead.io comment guidelines

Avatar
egghead.io

When a Todo property updates, you still must create a new Array of Todos and assign a new reference. This lesson walks you through refactoring from the current approach to the immutable approach.

Avatar
Nik

Nice videos! -- I just have a question about the toggle todo immutability approach. When before you reconstruct the todos array with slice(0,1) and etc, the todo in question whose status is set to completed by todo.toggle(), would't this mean that we are changing its state, an act that we try to avoid?

In reply to egghead.io
Avatar
John

Good catch ;) That's addressed in a later lesson, so keep watching! (and check out our other lessons on immutable libraries which are out of scope of this series).

In reply to Nik
Avatar
Mario

WHen it toggles, why not doing this.todos = [...this.todos] instead of looking for the index to mount again the same exact array in three parts?

In reply to egghead.io
Avatar
oalexandersson

WHen it toggles, why not doing this.todos = [...this.todos] instead of looking for the index to mount again the same exact array in three parts?

I want to know this as well.

In reply to Mario
Avatar
John

This is in preparation for a later lesson when we talk more about immutability. You wouldn't be using the "exact same array", you're making a brand new array composed of the three parts including copying the todo with the changed toggled prop (as opposed to updating a todo's prop).

In reply to Mario
Avatar
Andre

this.todos = [
...this.todos.slice(0, i),
todo,
...this.todos.slice(i + 1)
];

I don't understand how the todo item being toggled is being removed when it's being added back to the array in the todoToggle function?

Avatar
Andre

Answered my own question by looking back at previous code. I had forgotten about the 'started pipe' that was created in an earlier lesson, which is filtering the list of todo items that are then outputted by the *ngFor.

In reply to Andre

In exactly the same way that our search pipe requires us to update the reference to a new array whenever a new item gets added -- like swim -- if I try and toggle one of these and set up a pipe that filters out any of them that are toggled, that means that I need to update the reference to a new array whenever this property changes the status of that todo model. The pipe for that would look like this, where I can just copy and paste by search pipe.

I'll call it a started pipe. Pipes are basically just a name, so started, change this to started.

Then instead of filtering on the title, let's filter on the status. We want to check if a status is started, so in my todo list, I'll swap out search pipe with started pipe, started pipe, started pipe, and started. Now you'll see that it shows each item that is started.

If I try and mark these as completed, you can still see they're shown. They're not being filtered out. To make this work, we need the todo item renderer to notify the service and have the service create a new array with that todo that got updated changed.

In the item renderer, instead of doing todo.toggle, what we're going to do is dispatch a toggle event, so we need two imports here, output and event emitter. Outputs are how you set up custom events, we'll call it toggle.

You need to instantiate a new event emitter. Instead of todo.toggle in the click handler, we'll say toggle.emit and pass out the todo.

This is an event emitter which is going to send out the current todo to the parent component, which is our todo list. To handle that toggle event, I'll just create some new lines here just to make it easier to read.

We'll use the parens, just like we'd handle any sort of click event or anything. We can handle a toggle event, which we set up.

To handle this toggle, we'll set up a handler on our todo service, say toggle todo. Then pass in the event, because in our case, the event is the todo, which is being emitted from my toggle event emitter.

Toggle dispatches the todo, and then my todo list forwards it onto the todo service. Then in the todo service we can say, toggle todo and we can check that this is the right todo, so anytime I click here, you can see, I get the eat, sleep, and code.

Instead of just logging this out, I can say, todo.toggle, and I need to update my array to make this all work.

The way that we're going to construct this array is by finding the index of the toggle that got passed in, so this.todos index of todo. Let's call this I. Then use the index to grab every item before, which is this.todos.slice.

We'll start from zero, work all the way up until we find the current todo, and then use the spread operator to take each todo and just drop them into that array.

Then we'll drop in that current todo, which is the updated one, so this guy right here who is toggled. Then we'll finish it off using a spread version of todos, slice, and in our case, I plus one is going to give you every todo after the current todo that got passed in.

You can think of it as we're reconstructing the same array using the items before it, the items after it, and the current item. If I click on sleep, then this is eat, and this is code, and this is sleep.

I'll go ahead and save now. I'll toggle sleep. I'll toggle code. I'll add swim, I'll toggle eat. I'll add dance, and toggle those both away.

HEY, QUICK QUESTION!
Joel's Head
Why are we asking?