The Evolution Of Validation
Often times, the obvious interface for a feature is not-so-obvious when you're writing it. The process of not settling for less is invigorating to me, and this episode is a perfect example of that.
[00:00:00] Caleb: Okay. This one is straight up silly in hindsight. It's another invisible feature. So the validation and live wire as it stands. I'll describe to you how it behaves right now. If you have a form in Livewire and you have a bunch of input elements and you wire model those input elements two pieces of data inside your component.
So if you have a form with a name and an email, you might have wire model name while your model email and then on your class you would have to public property. Public money sign name and then email set to whatever the default so you want them to be. So if you wanted to validate on this, let's say I have a button called submit you'd listen for the submit method on a form or listen for a click method or whatever and fire a method inside your live where component or an action called submit then inside of their you want to do some validation. So the first thing I had this was the first sorry, I'm describing it as it is. Now, here's how it is. Now [00:01:00] you would do this Arrow validate and. Behaves exactly like request Arrow validate. Now you pass in your validation rules and the keys. So you'd say name name is the key and then the value is let's say required pipe Min six or something.
It will reference the value of the piece of data called name inside the component just as if it was like a request in laravel like you have data in a request and then you do request Arrow validate you pass in the rules and extra messaging and whatever and then it fires of elevation exception. Right? So this works the same exact way it works intuitively you look at it and you go. Oh that makes perfect sense. This is really easy. I get how to use it because I'm already using it this way. It wasn't always like that my first. In a validation in Livewire at first I thought okay people are going to want to people are going to want to have.
Multiple validation sets I was sort of picturing it like you would declare the validation on the component. [00:02:00] So at first I think I had a pup property called validates, which first I stressed out about that name was like protected validates. Is it validates or validator or rules? I didn't really know actually in hindsight rules is probably the best name, but at the time it was validate so protected validates equals and then you have an array that you declare of all the validation rules right on the class.
And then, you know just kind of how I. But it would be an array of arrays because I thought well you wouldn't want just one for a component. Let's say you had multiple sets of data that you wanted to validate inside that component. You need to have multiple. So started going down this whole Rabbit Hole of these concept of forms, like Livewire had the concept of forms at one point.
We're like and I forgot even how you would denote them in the template like wire: form and then the name and it would keep track of all that data and it would reference the specific that anyway, it was a mess and it was super complicated. So I went know instead of having [00:03:00] instead of having multiple on we're just going to stick with one because this is way easier.
So you just have this protected validates and then all the validation rules declared as a class property and then you have this Arrow. Inside of a method that calls on that protected property does the validation and does what it needs to do the problem with this one of the problems with this like a practical problem outside of it.
Just feeling weird. Is that so I guess okay. Here's the two problems. The first problem. Like I mentioned is it's restricted to one set of data when you're running this Arrow validate your running the validation for the entire component. That's problem. Number one problem. Number two is if you want Dynamic validation or anything like that, you're declaring it inside of a class property.
So you can't do any, you know, you can't like column method or anything, you know, you just have to use the string validation syntax. So those are the two small Hang-Ups. It just didn't feel Perfectly Natural. And again, this is one that through the process of user testing. It just [00:04:00] kind of got honed and I think I think Lucas Mitch it.
Yeah, so. Well, I yeah, I don't actually know. Yeah, so when I did a user test with Lucas Mitchell another core laravel contributor number like 2 or 3 or something, he he was super kind to do this and he was ridiculously helpful actually like change the course of Livewire by just you know handful of things he said. But he so I have notes here like this validates type of so clearly I can see that that it's this Arrow validates at the time and then I have all these notes for how to make the validation nicer. So I don't know if it was his user test or one after we're just realized that make the freaking validator function work.
The way request validate Works pass in do this Arrow validate and then pass in the rules as you need them and reference the data directly. I don't know. I mean it sounds this is kind of a silly one and as I'm saying it it's silly but it took a long time for me to arrive at that and I guess [00:05:00] it's just a story of a feature just not feeling great.
It just felt tacked on it didn't feel natural. It felt like I had created something that you had to learn how it works. But when I arrived at the perfect solution, which is this Arrow validates and then passing the rules. It makes sense to people they immediately get it it clicks. You can use anything you would normally use with requests are validate because I just forward to the validation stuff.
Anyway, you can pass in the same exact parameters. You can pass invalidation messaging rules, whatever it makes sense. Um, I guess in theory the perfect solution is to do or I guess the most invisible solution is to do request Arrow validate, but then I would have to hijack the request it would be nasty users would be like well am I they would get confused about what a request is.
So a money sign this Arrow validate I think is the perfect solution. It's invisible. You don't even notice you don't even notice it it just makes sense. It makes perfect sense and I don't remember the evolution of this but this was [00:06:00] another one. When you call that it if throw if you you know hit a validation issue, it will throw the validation exception that a normal request validator does and it will provide the money sign errors. Object the errors bag to the view that gets rendered. So that was just a like a tiny bit of hackery to do that. Like the implementation wasn't the hard part. It was coming up with the idea. And once I did it just felt Supernatural so validation just feels so native in Livewire and that that's a huge goal for me with Livewire and that is just the process of user testing and time is just making it feel like laravel making it feel like a first-class Citizen and basically any feature I try to see if.
Laravel conventions or functionality or something that I can pull on so that I get that familiarity and I'm not teaching you a new syntax that you're just either know it from vue.js or from laravel and that's sort of a [00:07:00] big overarching goal with Livewire is to just feel natural. If you're a view / level developer one of the while I'm sort of down this hole one of the issues that you come across with that is pulling from conventions. You get the benefit of the assumptions of the user. So the user gets the benefit of familiarity. They're familiar with how it works right away off the bat, which is great. And that's awesome. But they also have assumptions and if those assumptions are incorrect, you can cause confusion for them. So this is really tough balance. We're like the this Arrow validate that so a good example would be if I did request error validation. They would feel natural to them because that's what they're used to using but they might have questions like. Well is this data from the request is all the data just request data from reach live where I request.
Where does it come from what it you know that it is request hijacked. Can I not use your quest? Can I use your crust other places? Can I use form requests, you know it like leads them down these Trails of [00:08:00] thoughts that are incorrect. So it's kind of this really tight balance of balancing. Yeah that tension between like leveraging familiarity with.
And not confusing your users or misrepresenting the underlying technology and it's a tightrope. I continued to walk recently having conversations with Sebastian to dine about maybe adding some sort of props type syntax like view has for Livewire, but it would work subtly different in certain ways that it's just one of those concerns I have it's one of the first it's like I really want to add this.
I want it to feel natural like. But I don't want to confuse the hell out of people and and they you know, they're using this and they think well if I change a prop going into it, then the child should update right like stuff like that. So Live Wire is a joy to work on and this was one that I'm really happy with the outcome and feels like a supernatural solution.
Whoa. I saved you an entire minute or a minute early. I'll sign off now you can go eat [00:09:00] snacks with the time left. Before before whatever you're doing comes up. Okay. Thanks. Bye.