در حال بارگذاری ...

Choosing Link Input UX0:05

All right, let's see if we can knock out support for adding links to an idea. So yeah, as you can imagine, we could add one link to an idea or potentially five or 10. So we need a way to support that. And we have a couple choices. I think we're gonna take the approach of having a little input link and then next to it is a plus button. And when you click on the plus button, it depends another input,

And when you click on the plus button, it depends another input, and you can do that as many times as you need to. Ultimately, all of those links are included as one key that are then sent to the server. The only other option might be to have a full text area and keep it kind of quick and dirty. You might say, add a list of links separated by return. And then behind the scenes we explode that into an array and throw it into the database.

Building Link Fieldset UI0:42

And then behind the scenes we explode that into an array and throw it into the database. That works too. We lose a little bit of client side, uh, validation, but it's an option. Nonetheless, I wanna show you the first approach. I think it's useful. Let's go into our index page and I think we can add it maybe right down here below the description. Alright, so I think we should have a field set because there's a number of, uh, inputs here.

Alright, so I think we should have a field set because there's a number of, uh, inputs here. Yeah, so maybe we'll add a class of space Y three to separate the inputs and such. You'll see that in a minute. Uh, a field set needs a legend. That's effectively our label. So we'll call it links and uh, yeah, let's get to work. So we know that basically we need an input followed by a button with a plus symbol, right? So with that in mind, let's add a class of flex

by a button with a plus symbol, right? So with that in mind, let's add a class of flex and then just put a little space in between the input and the button itself. Okay? Now let's see. This input will have a type of URL so that we get some of that free client side validation. We are talking about. Uh, I'm gonna give it an idea of new link just in case we need to target it. I'll give it a placeholder to signal kind of what we expect

of new link just in case we need to target it. I'll give it a placeholder to signal kind of what we expect we could potentially do auto complete. Maybe if there's something they wanna complete there, maybe not. We'll give it a class. We're gonna use that input class. And because this is a flex item, let's make sure that it can flex and grow to fill any available space. Uh, let's turn off spellcheck. It's probably a good idea. Alright, and then, yeah, for the button itself, well,

Uh, let's turn off spellcheck. It's probably a good idea. Alright, and then, yeah, for the button itself, well, let's make sure it's not treated like a submit button rather than just a character. I think I have, I have an icon here. What is it? X icons. I think it's actually called clo. Oh, you know what I don't have in a pinned button. So I'll show you a fun little thing we can do. Uh, by default this will render as like an X, right? A close button, but we're just gonna be horrible people

Uh, by default this will render as like an X, right? A close button, but we're just gonna be horrible people and rotate it 45 degrees so that the X turns into a plus. Sloppy. Don't beat me up. What's the idea? And yeah, that looks pretty good to me. So we have our legend, we have an input, it fills the available space. And then, yeah, presumably when I click on this, it should create another input below it. Okay, so this sounds like a use case for alpine js, right?

Managing Links with Alpine2:54

it should create another input below it. Okay, so this sounds like a use case for alpine js, right? We need a way to track which links the user, um, has provided. So basically we want to say something like this. Like when you click on me, then we're going to push to a links array, right? And what are we gonna push? Well, we're gonna push whatever the new link is that the user typed in here.

we're gonna push whatever the new link is that the user typed in here. Alright, so I need a way to track what they typed in there. So I'm gonna use X model for this maybe right here, X model. And we called it new link. That's fine with me. Alright, so let's go up to our component here. I think it's defined on the form. Let's update this. So each attribute is on its own line, something like that. And yeah, now we need to track a new link.

So each attribute is on its own line, something like that. And yeah, now we need to track a new link. So by default that will be set to an empty, uh, string. But yeah, it also sounds like we'll have a links array. All right, so let's just check this out. Let's have some fun. Let's scroll down here. And maybe at the very bottom temporarily, I want to echo out the new link itself so we can see what we typed in there. And I'm sorry, thinking of PHP, uh, let's do x text,

so we can see what we typed in there. And I'm sorry, thinking of PHP, uh, let's do x text, uh, to new link. So if I add a link, sure enough, we can see that binding is in place. Perfect. Uh, what about the links themselves? Let's just say very quickly, type Jeffrey string. Apply the links one more time. So yeah, now if I type lar cast.com hit plus you can see we append to that array.

So yeah, now if I type lar cast.com hit plus you can see we append to that array. Let's do another one. Let Laravel dot com plus we pin, uh, pinned to the array. Great. All right. This looks good, but of course still some things to do. Uh, first up on the list is when we add plus. Well, maybe we should clear that out. I would assume so if I come back, Hmm. Let's see. So it sounds like, yeah, right here we don't just

I would assume so if I come back, Hmm. Let's see. So it sounds like, yeah, right here we don't just push, uh, a new link. We also need to empty out the new link itself. So I can say, all right, once you're done pushing, let's, uh, set new link to an empty string. Alright, so one more time, let's give it a shot plus it gets added, but then we clear this out. Perfect. Now, one thing we might wanna do, let's see, we probably wanna trim it just

Perfect. Now, one thing we might wanna do, let's see, we probably wanna trim it just to clear out any spaces you might have accidentally added. And that looks good. This could be its own function if you want, but we're gonna keep it in line just to keep things terse. Next, what about situations where we try to append the link, um, but we haven't filled one out? Well, if I hit plus, you can see this situation right there. So maybe what we do in those situations,

Well, if I hit plus, you can see this situation right there. So maybe what we do in those situations, and once again, let's just clean up. Yeah, maybe we say, well, this button is disabled. If the new link, um, length is zero, or check if it's falsey or something like that, this button won't even respond. Okay? So now if we were to give it a shot, I haven't filled anything out here. If I hit, plus it's not gonna work at all. And of course we can style it accordingly,

Submitting Links as Array5:46

If I hit, plus it's not gonna work at all. And of course we can style it accordingly, but if we do give it a valid link plus it works. Cool. So now we have a tricky situation because we're not submitting the form with JavaScript. It's not a client side form, it's still a traditional form where we need inputs with name attributes and that's what actually gets submitted. But at this point, we now have an input without a name, and then we're using JavaScript to uh,

But at this point, we now have an input without a name, and then we're using JavaScript to uh, create additional inputs and just gets a little bit tricky, right? So here's what we're gonna do a first option, and I'll warn you, we're gonna tweak this a good bit. But yeah, maybe a first thing you might do is say, well loop over all of the links. So for link n links, and keep in mind at this point,

So for link n links, and keep in mind at this point, this is Alpine, this is JavaScript. We're not looping with PHP, we are doing JavaScript stuff here. Okay? Yeah. At this point you could add a hidden input where you set the name. And this is really important. If we want all of the links grouped together when they're submitted to the server, we want them almost

If we want all of the links grouped together when they're submitted to the server, we want them almost treated like an array, right? And the way we do that with a form is of course, with this little syntax here, the key will be links. And I want it treated as an array. Alright? So let's set X model to the link itself that binds the value, right? And, uh, let's just see this. And actually before we make

And, uh, let's just see this. And actually before we make it hidden, let's make it visible. So it's, uh, very prominent to us. Add lar append. Let's do another one. Let's do Laravel dot com append. And once again, if we inspect this like, so we have an input with the name of links. So these are going to be shared and you'll see that when we submit it to the server.

So these are going to be shared and you'll see that when we submit it to the server. Let's go to idea controller, go to the store action. I'm gonna dye and dump the request. All come back, let's submit it or add an idea and then submit it. And sure enough, notice we have links and that's an array of two items. So that's ready, right? Because we have the as array object cast on our model,

So that's ready, right? Because we have the as array object cast on our model, we just say idea, uh, links equals this array, we save it and it all just works. Kind of cool, right? We can even now do validation. So within my request, I can say, okay, well I expect links to be, it can be knowable, it's not required. Uh, but it should be a list of URLs, right? So here's what we can do. Links should be knowable, uh,

So here's what we can do. Links should be knowable, uh, but if it's present, it should be an array. And then I can even validate each item within that array, which is super cool, like this links.star. And this would represent each item within links. Well, what should that be? This should be a URL, right? We could do the same thing like maximum 255. You can set a minimum, but a lot of that is handled because, uh, we're validating against A URL.

You can set a minimum, but a lot of that is handled because, uh, we're validating against A URL. Okay? So now check this out. If I give it a refresh, it's all still going to work because it's valid. But if we try it again, let's do a jish title and then a gibberish link. And yet, now if I create this, well it redirects back and we can handle that in a little bit.

well it redirects back and we can handle that in a little bit. But the important thing is we're not inserting an invalid URL into the database. Cool. So let's go over this. We have a field set for links, and the first thing we're gonna do is loop over all of the links that we currently have. And for each one within a hidden input, we will bind that link.

And for each one within a hidden input, we will bind that link. And again, we need that in order to make a traditional, uh, form submission. Okay? They will all share the same key, so they're grouped together. Next on here we will have a, an input and a button to create a new link. So we store the value using xmo. Remember that's a data binding.

So we store the value using xmo. Remember that's a data binding. It tracks what the user has typed in there, and then it re renders when it changes. And then when the user clicks on the plus button, well we will push to an array called links and that will re-render this section right here. Alright? So again, there's some aria stuff we could do. Like for example, on the button, as a general rule, whenever you have a button with no text,

Like for example, on the button, as a general rule, whenever you have a button with no text, you should use Aria label to describe what this is. Uh, add link button, stuff like that, or add new link, something like that. Um, but this is the gist of it. Um, some other things we might wanna do is just add some screen. Like there's a lot of accessibility stuff you're expected to do, and it's not great for demos, right?

Like there's a lot of accessibility stuff you're expected to do, and it's not great for demos, right? 'cause it's not that fun, but it's important to do. Or maybe, uh, right here you might wanna associate a label, even if it's not gonna be visible, it could be visible to screen readers only. There's a lot of stuff like that, um, you should probably consider, okay? But now, yeah, if you think about it, if we switch back, yes, we can add a new link here,

Adding Link Removal10:38

But now, yeah, if you think about it, if we switch back, yes, we can add a new link here, but we don't currently have support for removing the link, right? So that's something we need to offer as well. What if I changed my mind? Well, now I'm currently locked in, right? So that's not good either. Okay? So let's get to work. Let's come back and I'm gonna get rid of this pret tag for now.

Let's come back and I'm gonna get rid of this pret tag for now. We know what's going on and what I think we should do instead. Uh, I noted that we'll probably tweak this a little bit rather than making them hidden. Well, maybe let's just reveal those inputs to the user. So we'll say input type of text, which is the default. Give it a name, give it a model, give it a class of input. And now the user can physically see the link

Give it a name, give it a model, give it a class of input. And now the user can physically see the link that they've added here. Um, sorry. Plus, yep, that looks good. And now over here we can add like a close button to remove that one. Okay, so if we take that approach, yeah, it's gonna be very similar to what we have here, right? So let's duplicate that and then we probably need a button to close it.

So let's duplicate that and then we probably need a button to close it. Yep. But now, yeah, of course this is gonna be the button to remove link. So this should display as a close button. Let's get rid of the disabled. Let's have a look, come back, let's add a link plus and turn off. We can see it, but now I see a close button there. Okay, so now when I click on the close button,

We can see it, but now I see a close button there. Okay, so now when I click on the close button, we're just going to remove this particular link from the array of links. And yeah, this is standard stuff. We should be able to use links dot splice for this. So I could say click and we'll say links, splice. We're just gonna splice in there, grab this specific one and remove it. So I need to know what the current, uh, index is.

grab this specific one and remove it. So I need to know what the current, uh, index is. So this will give me the link itself and then where it occurs in the loop. And that way I can say, uh, index and remove one. All right? So at that exact point, I wanna remove one item. All right, let's see. Come back one more time, add it. Good. Now it's included, but I can remove it. And now it's excluded or, or deleted. Basically it works. So yeah, why don't we add a class.

And now it's excluded or, or deleted. Basically it works. So yeah, why don't we add a class. I think I have a form muted icon. Lemme see. I think I have something here. Muted icon form. Muted icon. Okay, let's use that one. And then I assume I should do the same thing down here. Come back. Yeah, it just makes it a little darker. Okay. Mostly this is an effect. Like I said, there's a, there's maybe some screen reader stuff we should probably do.

Like I said, there's a, there's maybe some screen reader stuff we should probably do. Uh, but in terms of the basic functionality, I can now add a link. Let's add another one here. You can see them at all times. This represents our new input link. And then when I click on create, once again with an idea controller, we're still dying and dumping. So if I submit this, that is past to the, uh, controller, okay?

So if I submit this, that is past to the, uh, controller, okay? So now, uh, let's just en ensure that it works and then we will update our test. And I think we'll be good to go. So one more time, refresh, finish submitting the form. Here it is. And there's our links. It's all working good. So let's delete that and then update our test. So let's head back and once again, programmatically, how can I target that?

Updating Tests and Review14:04

So let's head back and once again, programmatically, how can I target that? That's what I'm thinking in my head. Well, if I scroll down, we could definitely use new link. And I think that would honestly be fine. Uh, some teams will just have it in place. Like, nope, if you need to target it with JavaScript, you have to apply data test. And that makes it crystal clear that this input is being referenced from a JavaScript test.

And that makes it crystal clear that this input is being referenced from a JavaScript test. Um, but again, it's just whatever you wanna do there. Let's use the data test approach. Okay, I'm gonna return to create idea test. And let's do this one side by side. So let's fill, uh, new link with, you know, air tasks.com. Um, then let's click that button. So once again, we gotta name this, right?

Um, then let's click that button. So once again, we gotta name this, right? Submit new link button, that's fine. And then let's debug to make sure I, I didn't screw something up. Let's go here. And yeah, on the button I'll say data test, submit new link button. All right, and let's give it a run. All right, so here's our modal. I see the title, description and links is included.

All right, so here's our modal. I see the title, description and links is included. This is working good. So now when I submit the form, I can expect that links will be an array that includes layer cast.com. Let's run it and it passes. Awesome. So actually what I also wanna do is let's do it twice just to make sure I can add one or many links. So once again, I'll say fill new link with Laravel dot com, click it again, and then at that point, once we submit it

So once again, I'll say fill new link with Laravel dot com, click it again, and then at that point, once we submit it to the server, we should have lar cast and Laravel dot com. All right, one more time and that one works as well. Awesome. Okay, so a little bit tricky, right? There's just a, a handful of things we have to be aware of. And once again, I would recommend, like, what I would probably do here is pass this off to Code Rabbit, and maybe we'll do that in just a second just to see, okay, what,

to Code Rabbit, and maybe we'll do that in just a second just to see, okay, what, what accessibility related things do I need to include? Um, when I list them, should I add a screen reader only label for things like this? Uh, maybe right here we'd have a label with Tailwind. We can say screen reader only, and then this can be the current link, uh, in the loop, stuff like that. Uh, so with that in mind, let's switch over

in the loop, stuff like that. Uh, so with that in mind, let's switch over to Code Rabbit and it's done. Okay, so let's see what it has for us. Um, right here, fix the XMO binding to allow editing links and add a key attribute. There we go. Okay, so it did find, uh, one of the issues. Yeah, that's kind of standard stuff. And then, let's see, for the input, it wants me, um, yeah, it wants me to update it as the user is typing,

And then, let's see, for the input, it wants me, um, yeah, it wants me to update it as the user is typing, but, uh, I don't know if that is, uh, yeah, maybe we could do that. I was thinking of these as being read only, which is actually something we should update. So nonetheless, I'm gonna reject this, but I'm gonna apply the changes. So right up here we're gonna say key equals the index. So for the key, yeah, be careful,

So right up here we're gonna say key equals the index. So for the key, yeah, be careful, don't do the index, 'cause that will change. If it gets reordered. Let's just do, in this case, the, the link, the string link itself is, is probably appropriate. Okay? So if I switch back, that's it. No other request. So I think that is a reasonable, uh, job we did. Okay, so in the next episode, let's move on to steps. An idea can be associated with links,

Okay, so in the next episode, let's move on to steps. An idea can be associated with links, but also actionable steps. How do we do that?

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟