تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Plan Validation Component0:00

So we left off the last video with these inputs that don't have any validation on them, and if we enter an invalid value, we're not seeing that anywhere except in this little error bag that I'm throwing on the screen. That's obviously not what we want to do. So let's build that now, and let's do that by building a Livewire Blade component. So for us to test, I have added some kind of easy rules to not pass in our validation. So those are obviously not real rules that you would probably use, but I just want to make sure that we can regularly not pass validation. So the first thing I want to do is build out the API I want to use for some type of a text input.

Design Text Input API0:35

So the first thing I want to do is build out the API I want to use for some type of a text input. So let's go ahead and find one of these inputs. So here's one right here. And instead of all of this code right here, what I want to do is just have a x-text input, and all the things that I want to add on here, I'm going to build it out here first, and then I'm going to go build the actual functionality in the component. So we definitely want to wire:model something. So in this case, we've got name. We probably want to know what type of input it is.

So in this case, we've got name. We probably want to know what type of input it is. So this would be a text input. It could be a password. It could be numeric. We've got this label right here. So we're going to want to give a value for the label. In this case, it would be name. We also may want required. So I'll say required equals true here, which could be false.

We also may want required. So I'll say required equals true here, which could be false. And because I want the actual value true, I'm going to prefix that with a colon. We will also want some type of placeholder text, which we may want to use here. And then lastly, we might want to add some additional classes. So I'm going to add the class. And when I say class, what I'm kind of referring to here is some class I might want to apply to the outer div. I'm going to manage all of the classes that style the input inside the actual component. So I think that's a good API that I want to use.

Create Blade Component1:49

I'm going to manage all of the classes that style the input inside the actual component. So I think that's a good API that I want to use. Now we have to go build it. So the first thing we need to do is go into our components directory and add a new file, which would be text-input.blade.php. Let's add that there. Now the first thing I'm going to want to do is add some props to this, and that's going to align with what I just created on the previous page. So let's go back and take a look. We've got $yourModel is not actually going to be a prop.

So let's go back and take a look. We've got why your model is not actually going to be a prop. We have the type label, whether it's required or not, and the placeholder. The class is also not going to be a prop, and you'll see what that means in a minute. So let's go back and add these four as props. I'm just going to grab this and I'll paste them in here. And now I'm ready to set some defaults. So I think text is a good default for the type for label. Let's set that to be blank required. Let's make it false by default, and then the placeholder will be blank as well.

Let's set that to be blank required. Let's make it false by default, and then the placeholder will be blank as well. And again, I'm going to use Tailwind UI for this. So if I go out to Tailwind UI, and I can actually see they have this input with validation error. So this is everything I'm going to want. So I can just click the clipboard here and copy it, and let's paste it back into my code. And I want to just see what this looks like. So let's do a quick refresh. And so this is what I'm going to want. This looks great.

And so this is what I'm going to want. This looks great. So when there's an error, this is the treatment I want it to have. So let's go ahead and implement this. So the first thing I want to do is take this label and replace it with label, because that's what I passed in right here. Defaults to null. But in my case, I passed in name. Next up, the type of the input is text. So let's take a look at this and I like to put these all on the same line just to see

And actually, I'm looking at this, I need this to be the value false, not the string. And for placeholder, I do have an option right here. So I'll just say, placeholder. And then lastly, I don't want this value because I'm going to get that through wire:model. So let's get rid of that. We'll leave this error for now. Let's take a look at what we have. Everything seems to be good. Let's try to pass in a placeholder just to make sure that that's working. On this text input, my placeholder, and if I refresh, so the props are all really straightforward.

Handle wire:model Attributes4:19

Let's try to pass in a placeholder just to make sure that that's working. On this text input, my placeholder, and if I refresh, so the props are all really straightforward. But now let's get into the wire:model. And this is just a little bit more complicated because we have wire:model here, but we may not always have just wire:model. Sometimes we might want wire:model.lazy, or wire:model.debounce, 1000 milliseconds, something like that. So we have to do something a little bit different to get this over into our Blade component. So the wire:model and the class are going to be in my attribute bag. So let's go back to our component.

So the wire:model and the class are going to be in my attribute bag. So let's go back to our component. And let's actually just dd $attributes and take a look at that. Okay, so you can see I've got my two attributes. I've got wire:model is $name and then class is empty right now. Let's put some values into class just so we can see what happens here. Let's give it a lot of margin top and quick refresh. And now we can see here's what we have for attribute bag. So let's implement the wire:model. And what we could do if it was always going to be wire:model would be wire:model equals

So let's implement the wire:model. And what we could do if it was always going to be wire:model would be wire:model equals and then attributes.get('wire:model'). And this actually works great when you know that your attribute will always be exactly wire:model. So if we get rid of the die in the dump, and we do a refresh here, you can see if I type in here, it's going to update this because both of these inputs are modeled to the same name variable. So everything here is working. But if we go back to our component, and we change it to wire:model.bounce 100 milliseconds,

So everything here is working. But if we go back to our component, and we change it to wire:model.bounce 100 milliseconds, and do a refresh, if I type anything here, I get this exception. And so let's fix that. If I go back in here, instead of doing this, I'm going to delete it entirely. And I'm going to replace it with attributes->whereStartsWith wire:model. Again, let me grab this and let's dd it before we use it just to see a time dump. And let's do a quick refresh. And now you can see it's an attribute bag, but it just has the one wire or sorry, the

And let's do a quick refresh. And now you can see it's an attribute bag, but it just has the one wire:model or sorry, the one attribute that starts with wire:model. So I can just put that directly on my input, like so. And if I refresh the page, start typing, it all works again. And if I inspect this element, I can actually see here that I have wire:model that the bounce that 100 milliseconds equals name. So I was able to get that directly onto my input using the where starts with. Now there are other places in here that I actually want the value of name here. Like here, the label for is not actually email, I'd like that to be name.

Now there are other places in here that I actually want the value of name here. Like here, the label for is not actually email, I'd like that to be name. But I'm not going to hard code it, right, I want to pass it through into the Blade component. So what I can do there is I'll take this. And instead of just getting the attribute bag, let me get the first value out of it. And so I can copy that, put it right here. And now all of a sudden, when I refresh the page, if you take a look here, the label for is now name. And if that didn't quite make sense to you, let's just do it one more time with a dump and get rid of my curly brackets.

And if that didn't quite make sense to you, let's just do it one more time with a dine dump and get rid of my curly brackets. So when I do this, I just get the value name, which, again, is just what I put right here for whatever attribute starts with wire:model, I'm going to get the value. And of course, it's the first one. So if I had to, for some reason, which you wouldn't want to do, but if you had to wire:model on this, then it would only grab the first. Okay, lastly, I want to get this class and apply it to the parent div. So I want that right here. So again, the first thing I could do is just say class equals attributes->getClass().

So I want that right here. So again, the first thing I could do is just say class equals attributes, getClass(). And let's comment that out and give myself a quick refresh. And now you can see the margin-top has been applied. And that's actually going to work for me. But if I did have some additional classes that I needed to merge this with, you can actually see here in the layer of all docs that there's an attributes merge. And so I could take whatever classes I wanted originally, and then merge them here. So I'm not going to do that. But just know that that's an option for you.

So I'm not going to do that. But just know that that's an option for you. Okay, so now everything is basically done, except for the fact that when I come back here and refresh, it's always giving me the error treatment. And I want it to have the normal treatment until I get an error. So let's start stripping away the pieces that make an error message. So there's this little SVG right here. Let's see if we can find that and get rid of it. Let me just copy this and or highlight that and comment it out. If I refresh, it's all gone.

Let me just copy this and or highlight that and comment it out. If I refresh, it's all gone. So that's probably what I want. The other thing we have is this error message, which I don't need if we're not in an error state. So I'll get rid of that. We're getting a lot closer. And then the last thing is just this red which I want to get rid of, which that's all contained in here. Now I don't want to mess with figuring out which of these classes apply or which shouldn't.

Conditional Error Styling10:22

Similarly, these things that are commented out, I want those to show but only when there's an error. And actually, if we look here, these things should only show when there's an error as well. So the way that we can handle that is just by using Laravel's error Blade directive. And what type of error are we looking for? We want the attribute name. So if we just grab this, I'll take this here, put that in there, then I actually want this class to show, and then else, and here, and if. So let's just start with this one, take a look at our UI.

class to show, and then else, and here, and if. So let's just start with this one, take a look at our UI. And now you can see it looks just like it should. There's no error styling. But if I type something and hit submit, let's just try to do this. Now I've got the error styling here. I can get rid of this attribute bags, sorry, error bags. So let's just get rid of that. And let's change this email. I'm actually going to make this a text just to make it easier to do some testing here.

And let's change this email. I'm actually going to make this a text just to make it easier to do some testing here. If I refresh, let's take a look at that one more time. There I'm getting the error treatment. I'm still not getting the message, but we're getting closer. So let's take a look at our component again. And so this is what we want to check for before we show this. So now we can uncomment that. And in the same way, we want to check here before we display some type of a message. And instead of this hard-coded value, we just do message.

And in the same way, we want to check here before we display some type of a message. And instead of this hard-coded value, we just do message. Okay, so let's come back here, submit it one more time. Now everything is looking really good. We did have one more thing we needed to do, which is for these accessibility options. Let's do that. And now I think we're pretty much ready to go. So let's save this and let's see if we can refactor the rest of the page by just using these components. So we've got this one for name, and let's just add three more.

these components. So we've got this one for name, and let's just add three more. And we need one for email, so it'd be email. Let's take a look at our UI, company name, email, and password. Okay, and if we look at all of that, I think it's all good. So let's do a quick refresh. And now everything looks great. Let's get rid of the original ones, and let's get rid of that margin-top: 24 that we added. Now let's change this MT24 to something a bit more reasonable, like MT4, and do a quick refresh.

Fix Livewire DOM Diffing13:02

Now let's change this MT24 to something a bit more reasonable, like MT4, and do a quick refresh. And everything there looks pretty good, so let's just get rid of all the other divs that we had originally. Get rid of that. And a nice refresh, and now everything is looking really good. So if I try to register, and we got these error messages, and now if we type in here, it looks like it didn't quite work because some of these errors did not go away. And this is actually a DOM diffing issue in Livewire, and we can fix this pretty easily. To understand what's happening with Livewire, we have these error things where they either

And this is actually a DOM diffing issue in Livewire, and we can fix this pretty easily. To understand what's happening with Livewire, we have these error things where they either show or don't show based on whether there's an error state. And the DOM diff in Livewire has trouble keeping track of these things. So one of the ways that you can fix that is just to easily add a wire:key to anything that you're having a DOM diffing issue with. And then let's give it a unique key, which will just be, let's say, error. And grab at that. And in this case, we'll do the same thing here. Okay, and if we go back and let's give it another refresh and fill out the form one

And then let's just reset the errorBag of that value. So one more time, and this should do it. We've got errors. If I type something here, that error disappears, but the others remain until I try to fix those as well.

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