Extract NoToDos component0:00
Okay, let's work on extracting some components here. In that process, we're going to have to learn how to share state between components and how they can communicate with each other. So right now everything is within this one component, which is fine. But at some point, you do want to extract the multiple components to clean up your code. So let's go ahead and do that. Let's start with something simple here. Let's extract to a Component when we have no toDos, we have this container with the SVG. So let's start with that. So I believe that's called NoToDosContainer. And it's one root node here in our else block. So let's go ahead and extract this to a Component. So let's grab all of this. I'm going to name it NoToDosContainer. Okay, let's make sure it's capital N. Let's bring back the sidebar here. Let's create that new Component, NoToDosContainer that's felt. Let's paste in that markup. And if you scroll up here, you'll see we have this red
capital N. Let's bring back the sidebar here. Let's create that new component. No todos container that's felt. Let's paste in that markup. And if you scroll up here, you'll see we have this red squiggly for no todos container. And if we go back to our app.svelte here, you'll see that we're only making use of that in one place. So right here, we have the variable for it. And it's just a reference to that DOM node. So we can safely just move this to our new component. And that should be fine. So let's grab this, go back to our component. Let's go back to the top here. Let's add a <script> tag. And it's based in that variable. Looks like we also need this fade transition here. So let's grab the import from app.svelte. So this one right here, we can put that in there as well. And it looks like we only need fade here. So we'll get rid of these. Okay, let's make sure to import the component correctly within here. So no todos container. Let's make sure to import it here. I'm
Extract ToDoForm component1:33
And it looks like we only need fade here. So we'll get rid of these. Okay, let's make sure to import the component correctly within here. So no toDosContainer. Let's make sure to import it here. I'm gonna hit tab VSCode should have imported that up here. There it is. And hopefully this should still work. So let me save this. And if we try that again, it should still work hopefully. And it does cool. So what we've done here is introduce a component tree. So think of it as a tree like structure with one root node. In this case, our root node is App. And that can have multiple children. So in this case, we have one child for our toDosContainer component, but it can have multiple children as well. So let's extract more components here. How about we extract one for our toDoForm here. Let's go ahead and do that. So let's look for the form here should be right here. Okay. And we'll make a component for this. So let's grab this, same it to toDoForm. Okay, let's make a
to do form here. Let's go ahead and do that. So let's look for the form here should be right here. Okay. And we'll make a component for this. So let's grab this, save it to ToDoForm. Okay, let's make a new file for that. ToDoForm that's vue. Let's paste that in. Let's save that. Let's make sure to import it correctly within here. Again, I'll use VS Code to import it to tab. Okay, let's save that. So I restarted my server. And you can see the app is no longer working. You can also see we have this red squiggly here. So let's go ahead and fix this. So you can see it says toDoTitle is not declared. So since we extracted this to its own component, it no longer has access to the state of the parent component. So toDoTitle is defined in App.vue. So it should be in the script section right here. And you can see that it does need it here when we're adding a new to do. And it clears it out after we do that. But aside from that, the rest of the app no longer needs it. So
section right here. And you can see that it does need it here when we're adding a new toDo. And it clears it out after we do that. But aside from that, the rest of the app no longer needs it. So how about we move this date to our new component here. And we'll work on the rest in a second. So let's add that to our toDo form. Let's add a script section up here. Let's add that state. Okay, save that. Let's see if our app works now. Okay, now we have this squiggly on addToDo, because addToDo the method doesn't live within this component, it lives in the App spelt component. So you can see addToDo is not defined. So how about we define a local one in here. So it's a function addToDo. Sorry, there should be within the script section. So let's move that up here. Doesn't need any params. And for now, how about we just clear out the title. So let's say toDo
Child-to-parent events4:44
So for this, we can make use of component events. So from within the child here, we can emit an event saying that a to do was added. And then in the parent, in this case, in the App.svelte, we can listen for that event, and then act accordingly. So let's go ahead and do that. So back to our to do form, we have to create an event dispatcher. So this component has the ability to emit events. So let's do that first. So let's say import { createEventDispatcher } from 'svelte'; Next, let's define a variable which allows us to dispatch events. So say const dispatch = createEventDispatcher(); Okay. Now from within here, we can emit an event using that dispatch method. So let's say dispatch an event named, let's name it to do added, we can pass in any params that we want. So in this case, we'll pass in the to doTitle. So we can say to doTitle is to doTitle,
let's name it toDoAdded, we can pass in any params that we want. So in this case, we'll pass in the toDoTitle. So we can say toDoTitle is toDoTitle, or because it's the same name, we don't need to provide that. That's fine. Now in the parent App.vue, we can listen for this event and act accordingly. So let's go to where we define that component. So ToDoForm, we can listen for the event right here. So we can say @toDoAdded. And you can provide a method here. So let's provide the addToDo method. But we have to make a few small changes here. So let's go to that method. Before it was grabbing the toDoTitle from this toDoTitle field. But now the state is within the child component. So we can no longer get it from there. Remember, we're passing in the toDoTitle here when we dispatch the event. So we can accept the event here. And to grab the params that are
child component. So we can no longer get it from there. Remember, we're passing in the toDoTitle here when we dispatch the event. So we can accept the event here. And to grab the params that are being passed through, we can say event.details.toDoTitle. Again, we don't need the toDoTitle anymore. So let's get rid of that, we can get rid of it in here as well. And that should be good. And I seem to have a typo here should be event.detail, not details. Okay, let's try that one more time. And it does work now. Be sure to note that component events are only emitted to the direct parent. So in this case, we have our ToDoForm, we're dispatching this ToDoAdded event to our direct parent. And in this case, App is our direct parent. So we can listen for it in here. So again, we're listening for it in here. Then we call the addToDo method. And that works. So again, this won't work if there was another
Forward events through middle7:08
direct parent. So we can listen for it in here. So again, we're listening for it in here. Then we call the addToDo method. And that works. So again, this won't work if there was another component in between. So let me show you that and I'll show you how you can forward events. So let's add another intermediate component here. We'll name it ToDoFormMiddle. So let's go ahead and add that. So ToDoFormMiddle, that's felt. And all this is going to do is call the actual ToDoForm. So let's say ToDoForm. Let's make sure to import that. Okay, I should have imported up here. Let's save that. Let's make sure to save our App.svelte as well. Or we have to import ToDoFormMiddle from here. Okay. Save that. Let me just refresh this to make sure. But now if I try to add a new to do here, this should not work. And it doesn't. So again, let's go through the component tree here we have our root component App.svelte it has a child named ToDoFormMiddle, which is this.
a new to do here, this should not work. And it doesn't. So again, let's go through the component tree here we have our root component App felt it has a child named TodoForm middle, which is this. And all this does is call TodoForm, which is right here. And our TodoForm is the one that dispatches this event called todoAdded. And only its direct parent can listen for that event. So right now our TodoForm middle is not listening for that event. So therefore, it's not being passed to the parent. So it's not working. So we can't add to dos. So to fix that, we can do the same thing we did in here, where we dispatched an event to the parent. So let's go ahead and do that. So we'll grab this. Within the TodoForm middle, let's listen for that event. So let's say on todoAdded. Let's call addTodo spaced in that method here. So now we're dispatching to our direct parent, we can grab the params that were passed in from the event. So that would be event
do added. Let's call addToDo spaced in that method here. So now we're dispatching to our direct parent, we can grab the params that were passed in from the event. So that would be event.detail.toDoTitle. And that's going to be the same name. So toDoTitle, okay, and we don't need this anymore. And hopefully that should forward the event to the parent and addToDo should work again. So let's save that. Actually, I forgot to import the dispatch method. So let's grab that from here as well. So we need these two. Let's paste that in here. Let's try that one more time. And hopefully it works this time. Okay, and it does. So we can forward events this way. But this seems like a lot of boilerplate code just to do that. So Svelte actually allows you to do all of this without the need for all of this boilerplate. So if I were to comment all of this out, and change this to onToDoAdded,
the to do title, and then we made use of component events to dispatch an event that our direct parent can listen for, and then act accordingly. Now if your component tree is multiple levels deep, then you're going to have to forward that component to its direct parent. So in this case, the to do form middle component forwards the event to its parent. So in this case, it's listening for to do added, it forwards it to its parent, which is App selt. We're listening for that in here. And then we call the addToDo method once that event happens. So when we call this method here, we do have access to the to dos variable within here. So we can mutate it directly. And in this case, we are just updating our to dos. In the next video, we'll continue and add one more component here for our to do list, which will be the rest of our app. Again, you can have separate components for this. For example, you can have one for this, this, this and this. But we'll
Commit component changes11:02
one more component here for our to do list, which will be the rest of our app. Again, you can have separate components for this. For example, you can have one for this, this, this and this. But we'll just keep it simple with one more component here for our to do list. So for now, let's go ahead and make a commit here. So git add, git commit, episode five, let's say component communication using events.
