Register Alpine Component2:22
we update it. That would be an option, but at some point we will need to evaluate these words and evaluate each letter within the word. So, with that in mind, maybe we should declare our board as a source of truth in our data object. But if we're going to do that, I think it would get pretty messy very quickly here. So, I'm going to show you how to, when you need to, extract your component into a function. So, I'll show you how to do that. Let's get rid of this, and then in my app.js file, the first thing I need to do is listen for when Alpine is ready to go. So, we do that by adding an event listener called AlpineInit, and yeah, Alpine will hit that event or trigger that event when it's ready and initialized. So, for example, I could say, alert, Alpine is ready to go. And if we try this out, give it a refresh, we get the alert. Okay, so we can register a component outside of the DOM
and initialized. So, for example, I could say, alert, Alpine is ready to go. And if we try this out, give it a refresh, we get the alert. Okay, so we can register a component outside of the DOM using Alpine.data. So, let's call ours, how about game? And yeah, now this can return an object. So, for example, if I were to reproduce what we have, and for now let's hold off on that key up, but yeah, I could take this whole object here and simply move it like so. Now I can set x-data to game. And now if we switch back and refresh, yeah, we get the same thing. So, this is an option in situations where your Alpine component either needs to be reusable or it's just a little too much to store directly in the DOM. But yeah, now we have full control. If you only have three guesses, that's all being reflected here. Cool. So, now, yeah, we have a little more room to work with. We can set up our board. And we can do that by listening for the init method, which Alpine
Initialize Board State4:00
guesses, that's all being reflected here. Cool. So, now, yeah, we have a little more room to work with. We can set up our board. And we can do that by listening for the init method, which Alpine will, again, automatically hit in these cases, like so. And yeah, here we can create the board. So, our board is going to be basically what we've done here, almost exactly. So, I could say the board is array from length is this.guessesAllowed. And then for each row, yeah, you should be very familiar with this. And then here, we'll make another one where the length is the wordLength. And yeah, just to show you, if we were to return x for each tile, we now have our board. Now, remember, anything we define here is instantly available on our main HTML page, which means, yeah, we could swap this out where I could say for each row in our board, generate a div with a class of row. And then for each tile within that row, generate a tile div.
yeah, we could swap this out where I could say for each row in our board, generate a div with a class of row. And then for each tile within that row, generate a tile div. And if I come back and refresh, I get not the same thing. Let's see. Unexpected token. Whoops. Fix that. And there we go. Okay, so now, I think this is going to be useful because when I need to re-render this board, yeah, I have instant access to it. And I can even dig into this array and update, for example, each of these items. And actually, on that note, notice how I set it to x, but you're not seeing it here. Why don't we say x text equals the tile. Come back, refresh, and now we have the beginnings of our board. But yeah, of course, right now, I don't want to hard code x. So what do we put here? We can make an empty string. Maybe it could even be an object at some point. I'm not sure. So yeah, check this out. If I switch back now, when the user presses
Handle Key Presses5:51
code x. So what do we put here? We can make an empty string. Maybe it could even be an object at some point. I'm not sure. So yeah, check this out. If I switch back now, when the User presses a key, why don't we call a method like onKeyPress, and I'm going to send through the key they pressed. Okay, so I can define this function here again in our script file. Like this. So I could say, once again, let's do console.log(alertKey). All right, open up the console, refresh, press the letter G, F, D, S, A. It's working. Cool. Now, as you can imagine, we'll need to do a little validation to make sure you pressed an acceptable key. We don't want to respond if you press a number or the pound sign or the percent sign. But we'll get to that in a minute. For now, I just want to show you how to re-render the board. Now, if you think about it, they've pressed a key, so I almost want to go into this board and say, okay, get the first row, and then get the first
want to show you how to re-render the board. Now, if you think about it, they've pressed a key, so I almost want to go into this board and say, okay, get the first row, and then get the first tile within that row. And I now want you to set its body, or its value, to the key that was pressed. And then remember, because we're using AlpineJS, and that will then trigger a repaint, a re-rendering. So let's give that a try. We'll say the board, which is an array, the first item in the array is the first row, and then the first tile in that row will now be equal to the key that was pressed. Come back, I hit the letter W, and how cool is that? But yeah, of course, right now, every key I press will simply update that first tile, and we don't want that. So now you can see we need to be tracking, for example, what row are you currently on, and potentially what tile are you currently on. So let's see if we can do it. The current row, or really,
the given key, and then we'll add that here. And I'll paste all of that in. Okay, and that reads fairly well. When a key is pressed, if it's a letter we support, then fill the tile with the given key. But I don't love the fact that I have to track all of this. I think there might be a way around this. So let's see if we don't track the current tile, we could get rid of that, which means this then needs to be dynamic. Or maybe what we could do is say get the current row. So this bit of logic right here gives us the current row that we're on, right? And in fact, if you wanted to, we could even add a little helper method here called currentRow, and that would return that, like so. Alright, clean this up. So yeah, then we could say this.currentRow, and then maybe map over it. Actually, you know what, I'm not sure if this will work. Could I just do something like that? Would that work? No, it doesn't. No error there. Yeah. I think
Create Tile Objects11:46
row, and then maybe map over it. Actually, you know what, I'm not sure if this will work. Could I just do something like that? Would that work? No, it doesn't. No error there. Yeah. I think each item here should be an object, like a Tile. And this gives us a place to store extra information about each tile, like the state that we looked at in the second episode, where we learned the way the actual Wordle site works. For each tile, they track whether it's correct or present or absent. So this would give us a place to store that. Okay, right up here, why don't we, this could be an object or a class, we could have our Tile, and then we're going to have, I guess, the letter for it, like that. And yeah, then also the status, whether it is correct, present, or absent. Yeah, something like that. Okay, so I think the benefit to that is now, because I have an object, I could iterate over it, and then say tile.letter equals the key
first tile or the current tile. That was the problem we were trying to solve. So we need a way to break out of here. Yeah, obviously, we can't do it like that. So we would need to switch. So I could say for let tile of the current row. Yeah, this should work. Then set the tile's letter to the key that was pressed, and then I can break out of it here. So yeah, this isn't quite right yet, but I bet it works if I hit the letter R. Yeah, but now notice each letter will update that first column again. But check this out. I could say only update this if the tile letter is null or empty. So for example, if it's an empty string, only on that condition do we update it and then break. That's kind of a cool way to do it. Refresh, T-R-Y, and that works. And it avoids the need to track the current tile index. Now I suppose here I could also change this to if there is no tile letter, only then do we set the key. And again, remember, what's nice is because tile is
track the current tile index. Now I suppose here I could also change this to if there is no tile letter, only then do we set the key. And again, remember, what's nice is because tile is a class or an object here, if we have additional behavior that we need to stack on, we now have a location to put that. So this is right here. This is a silly example, but if I hit a lowercase T and an uppercase R, notice we're responding to both capital and lowercase. So I say it's silly because of course in your CSS, you could just say text-transform to lowercase and we can force it. But again, maybe you want a setter in that case, like tile.fill with the given key. Yeah, maybe you want a method like that. Well, now you have a place to put that. Fill with the given key, where this would then set the letter to the key, but you could even do key.toLowerCase(). Yeah, that's all I'm saying is you have a place to put this kind of functionality. So uppercase T-R-Y,
Refactor into Modules15:27
where this would then set the letter to the key, but you could even do key.toLowerCase(). Yeah, that's all I'm saying is you have a place to put this kind of functionality. So uppercase T-R-Y, and it still gets converted to lowercase. And now we could even do things like if I want to empty the tile, this would set letter back to an empty string. And maybe as part of that, we would update the status. I'm not sure. But again, we have a location for this. Okay, so let's do a little bit of cleanup, and then we'll call it a day. I'm going to add a new JavaScript file for our Tile class. And I'll grab this, move it in like so. And we're going to make that the default export. Cool. So now I can import that here. Import Tile from tile. Next, this object here is basically our game. So let's create a game.js. And then I will select everything up to that and move it over like so. And again,
here. Import tile from tile. Next, this object here is basically our game. So let's create a game.js. And then I will select everything up to that and move it over like so. And again, export default object. And then if I come back here, we could import it, import game from our game, and then assign it here. And we can get rid of tile there. Yeah. Okay, so now app.js is our entry point. We listen for when Alpine is ready to go. And then we register this game object as an Alpine component. This game contains, excuse me, sorry about that. Reformat. This game contains all of the behavior and data to track the user's progress. We then reference that within our template, and we're off to the races. So refresh, T-R-Y, and we're making some progress here. I'll see you in the next episode.
