Check out a free preview of the full Svelte Fundamentals course:
The "Selecting Squares" Lesson is part of the full, Svelte Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Rich implements logic for selecting squares, including resetting the selection if the contained emojis don't match and resetting the incorrect selection timeout to avoid interaction errors.

Get Unlimited Access Now

Transcript from the "Selecting Squares" Lesson

>> So we've got data going down into our components, but now we need to get some user interaction causing events to come back up, otherwise we don't have a game. So we'll begin by adding a button inside the square component. And we're gonna use the event forwarding shorthand that we learned earlier.

[00:00:22] To do on click like that, and we're gonna give the button some styles so that it fills the square. We'll give it a position absolute width 100%, height 100%. You now see the button filling the square. And because we have that click handler, we can start listening for that inside our grid.

[00:00:49] We start typing on click. It already knows that click is one of the events that this component can broadcast. So inside there, we'll start adding some logic. Now there are various states that the game could be in when someone clicks on one of these buttons. The first state is the one that we have now, nothing is selected, or there could be one card that has so far been selected.

[00:01:21] In other words, the card has been flipped over and we're revealing what is on the other side. And then we're gonna select the second one. Or we could be in a state where two cards have already been selected, we need to handle each of those separately. So the easiest one is, what if nothing is selected so far?

[00:01:49] Well, we need some way of representing that state inside this component. So I'm gonna create some more variables. We'll call them a and b, a is a string and b, in fact, no. We can use an index here. So it's gonna be a number, a is a number and b is a number.

[00:02:08] And in fact we can initialize these to -1, that can be our layer of representing the a and b both currently unselected. And when we do select one of these, we can set that to be index within the array. In order to know the index inside the array, we need to add the comma i to each block And we'll begin by saying, that if a is -1 and b is -1, then nothing is selected, so in response we need to assign the current index to the a value Do that like that.

[00:02:55] All right, if I hit Save, pretty is gonna format all of my messy code for me. Okay, well, how do we represent that new state in our app? Well, we're gonna need to pass that information back down into the square component. So we'll add a new prop on a square.

[00:03:19] Export let selected, that's gonna be a Boolean. And we can add a class to div class equals square like this. In fact, let's call it flipped, because that's how it's gonna be represented in the user interface when we get round to making this look more like a game.

[00:03:42] It's giving us an error because flipped is not a value, so we'll make that like this, okay? And then we'll add some styles for that state, had a flip class. In fact, let's add it on the button. Add some more ugly background colors. Inside our grid now, we're gonna see that there's a red squiggly under square because we are not passing in a prop that the component expects.

[00:04:16] Fix that, selected equals, a equals i or b equals i. Right, so for each iteration of this loop, if a is 0 or b is 0, then the zeroth element of that array should be selected. So hopefully, if we wire this up correctly and I press one of these buttons now, right?

[00:04:43] It's gonna turn that Into a selected state, but only if we're in that state where nothing so far was selected. One other little detail here, you'll notice that if I click on the emojis, the button does not get clicked, that's annoying. So on the span, we're gonna add a point to events, none.

[00:05:01] That allows us to click anywhere inside that button and it will have the desired effect. All right, so let's carry on with this logic. So we've handled the first state where nothing was selected. What about when a is selected but b is unselected? In this case, we have two possibilities.

[00:05:37] The first possibility is that we selected a pair. The second possibility is that we selected something that was not a pair of the already selected elements. So we'll have another if block in here. If grid a equals grid b, congratulations, we found a pair. Otherwise, incorrect. And we'll put in some logic for that case in a minute.

[00:06:07] Otherwise, if neither of those conditions are true, then it means that we've already selected a and b. And then we need to flip those back over and start again. So b is gonna revert to -1, and a is gonna become whatever we just selected. So now if I click this one and then this one, nothing's happening.

[00:06:34] Where did I go wrong? Because I forgot to add that. Okay, so now we have both a and b selected. If we select another one, it will reset the selection and get rid of the selected state on b. That's okay but in any memory game like this, normally what happens is after you've selected a pair, they get hidden immediately afterwards so that you can't like stare at them and make notes.

[00:07:08] So we're gonna add a timeout that makes that happen in the case where we got it wrong in the incorrect case. Could do you set timeout. After a second, we'll reset a and b both to -1. We have to be careful though with set timeouts because you could find a situation where the set timeout callback runs after the user has continued selecting other squares.

[00:07:39] So we need to be able to cancel that when necessary. So up here I'm gonna create a new variable, let reset timeout, and that's gonna be a number. And then I'm gonna assign that to the setTimeout call. And then basically every time I click, I'm just gonna clear that timeout, so I don't need to worry about interactions clobbering each other.

[00:08:11] So hopefully, we've done this right. If I select two cards, they'll stay selected for a second, and then they'll become unselected. If I select another card within that window, then it will just reset the timeout and carry on with a new selection, like so.