Planning the Poll Object and Custom Event
Okay then, so we've seen now that this form all works and when we submit it we get this object fields which has the question, answer A, and answer B. Now in the future, what I'd like to do is have an array of data registered inside the App component over here, and that would be an array of objects. And each object would be a poll, and each object would have a question, answer A, answer B, but also a few other things. It would also have a property for votesA to track how many votes A has, and votesB to track B's votes. And also it would have an id field, and that would be unique.
So let's go over to the CreatePollForm and let's first of all compose a new poll object down here. And then what we're going to do is emit a custom event, pass that poll object into App.svelte, and then we can add that new poll object to a polls array of data. So let's first of all...
Emitting a Custom Event with createEventDispatcher
...import at the top the createEventDispatcher.
So import { createEventDispatcher } from 'svelte'; like so. And then also we need to create the dispatch function. So let's do that right here. I'm going to say let dispatch = createEventDispatcher(), and invoke that. So now we have our dispatch function ready to use. And we're going to use it down here, but let's first compose that object, that new poll object.
So I'm going to now say let poll = a new object. And inside this object, first of all, I want to spread out all the properties from fields. So remember that's this object right here. So we're adding the question, answer A, and answer B that a user inputs into this new object. But also we need those extra properties. So votesA, and that is going to be 0 to begin with, and votesB, and that is going to be 0 to begin with as well. We also need a random ID, so I'm going to say id is Math.random(). Again, not the best way to get a random number, you might use an external library in the future to do something like this instead, but for now, this will do.
So we now have this poll object. We want to add this to an array of data inside our belts. So we need to now emit a custom event instead of logging this to the console. So let me now say dispatch, and we're going to dispatch an event which we'll call add, because we're adding a new poll. And the data we want to send along with that event is the poll itself, this thing we just created.
Handling the Custom Event in the Parent Component
So now we can listen for that event inside App.svelte, and we do that down here on the CreatePollForm. So on:add, and we set that equal to some kind of function. So we're going to call this function handleAdd, so handleAdd, like so. Spell this correctly. Okay, handleAdd.
We need to create that function now, but before we do that, I want to create some polls data. So I'm actually just going to copy this from my repo, and I'm going to paste it right in. In fact, we'll do it below tabs right here. So all I'm doing is creating an array, and it's called polls. And in that array, I'm adding a dummy object to begin with. Okay, just so we can see a poll to begin with on the page over here. But later on, we'll maybe start this as an empty array, and then they'll only appear when we add data to it. But for now, we have a dummy poll object inside it. And that has an ID of one, question "Python or JavaScript?", answer A is Python, answer B is JavaScript, votesA is 9, votesB is 15. Okay, so totally random part.
Now I need to create this function right here, handleAdd. So let me do that. I'm going to say const handleAdd = (e) => { ... }. We take in the event object because we need to get the data we send along by using a detail property on that event object. So I'm going to say right here const poll = e.detail;. So the object that we send along with the event. And then I'm going to say that now polls, which is this array right here, is going to be equal to a new array. Remember we have to reassign this. And inside that array, we're going to take the new poll and add that, and then after that spread out the current polls. So everything currently inside polls will be inside the new array as well.
Now I just want to also say down here console.log and we're going to log out the polls. So every time we add a poll and this fires and we update the polls, polls should be different, right? So let me save this and let me go to add a new poll. I'm going to say, "Do you like Marmite?", and I'm going to say "Yeah" and "Nah". And then I'm going to say add poll. And now we can see without putting polls, and it now has two elements. It has this one we just added, "Do you like Marmite?", but also the dummy one that we added to begin with right here. So let's just add another random one like so and make sure this works. And now we can see polls has three items inside it. Okay, so we're keeping track of those polls now.
But I also want to do one more thing inside this function, and that is once we've submitted the form, I want to switch back to this view automatically. Now we can do that by updating the activeItem right here, because remember we pass that value into the Tabs right here, and we also do a check on the activeItem to decide what content to show. So I'm going to set activeItem right here equal to current polls. So it was add new poll, which is why we saw the form, but once we submit the form and we add that poll to the data, then we're going to switch it back to current polls so that this shows instead, not the form anymore. That makes sense to me.
So let me save that and test it out. Add a new poll, load a junk in here, add poll, and then it switches back to current polls. And eventually we will output all of the different polls here.
Creating the PollList Component and Passing Props
In fact, let's just start that process now. I'm going to create a new component and it's going to be called PollList, and this will be the component that cycles through the data and outputs a list of polls. So PollList.svelte. And inside the PollList, we're going to have to have a script tag at the top because we're going to accept some props. There might also be some logic in there later on, we'll see. Then we also need a template, so I'll do a div for now with a class of poll-list. I'll come back to this in a second. And then we'll do a style tag as well to style the poll list.
Now we need to pass in some props into this component and we also need to display this component inside the App file right here. So let's first of all import it. So I'm going to just duplicate this, and instead of Footer, we will say PollList, and we need to do that over here as well, PollList. Then we can render it down here in the template, and it goes right here. So PollList, and we need to pass down a prop, which is the current polls, because it's going to cycle through those in the PollList component. So we'll say polls is equal to polls. Again, we can shorten this because this word and this word are the same, so we don't need the left side, it implies that. And save it.
So now we can accept polls inside this poll with the component. So I'll say export let polls, and it's going to be equal to an empty array to begin with. So that's the default value, but as soon as we pass down a prop, it overrides that value. And to begin with, it's going to be just an array of one element, but as we add more it will become 2, 3, 4, 5, 6, etc. elements inside that array.
Iterating and Displaying Polls with an each Block
So now we have this polls array right here, we can cycle through it. So to do that, let's do an each block. So {#each}, and then we want to cycle through polls and refer to each poll as a single poll. And we also need to register the ID property of the key property on each poll. Now remember that's going to be this thing right here, id. So in parentheses after this, we say (poll.id). Okay, so let's end this each now right here, and inside I'm just going to do a div for now which outputs the poll questions. So I'll say poll.question like so, and save it.
So now on the page we should get a list of poll questions right here. Okay. So let's see this, and to begin with we just get that one poll question because that is the dummy data we start with. But if I add another one, "Do you like Marmite?", and "Yep" and "No", and at the poll, we can see we have that question as well. Okay. Now we're going to expand on this template later on when we do the poll details, but for now that's fine. We can cycle through them, that's all I wanted to demonstrate.
Styling the Poll List with CSS Grid
Now I just want to style this poll list a little bit so that these things are not in a list going down, but rather in a grid going across. So we have one on the left, one on the right, then it goes to the next row. So to do that, I'm going to grab the poll-list and inside I'm going to display this as grid.
Now I'm not going to go into any depth about what CSS grid is, that would take several videos, but I do have a whole playlist on CSS grid on this channel. So I'll leave the link to that down below if you want to learn more about it. But essentially, this is just going to display our different polls in a grid-like fashion on the screen.
Now we need to specify a grid-template-columns property, and that is going to be 1fr 1fr. So we're saying here there's going to be two columns on the page, each column is one fraction of the width. So this is one poll which is going to take up half of the width and the other poll is going to be on the right which takes up the other half of the width. That's what each row is going to look like. Then what's a grid-gap and set that to 20px. So that property right there means that between each column, we have a 20 pixel gap so they're not bunched up right next to each other. So save that and let's have a look what this looks like. And we can see just one at the minute, but if we add another, "Do you like Marmite?", "Yep", and "No", then add new poll, we can see now it goes on to the right and they're going to display in this grid-like fashion in the future.
So I think that's enough for now. In the next video, we're going to dive into this bit a little bit more. So we're going to output some different details about the poll, the different votes, the different options that we can vote on, etc. So we'll do that in a new component called PollDetails and we'll register it right here. So we'll do that in the next video.