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

Auto-generating slugs on blur0:00

Here, we have a form that's been created using the filament form builder. We have a name field and a slug field. Let's type something into the name. And when I blur the input, a slug has been generated from this name. Now how does that work? Here is the code we're using for the text input. As you can see, it's been set to live on blur. Now this means that Livewire is syncing the value with the backend each time that the field has been blurred. And a side effect of that is that the field is also being re-rendered.

field has been blurred. And a side effect of that is that the field is also being re-rendered. This after stateUpdated function is also being run each time that the field is blurred. Here we're accepting a string of the operation, the state, and set. Now these are three parameters that are included within Filament FormBuilder and we call them formComponentUtilities. They help you do stuff dynamically with form components when the form is being rendered. So in this case, we're doing something different based on what the operation is. And this allows us to customise the behaviour of this form so that we're only generating a slug on the create page.

And this allows us to customise the behaviour of this form so that we're only generating a slug on the create page. As you can see, this state parameter here is being passed to string slug. And this is the current value of the name. set is the last parameter we're using here and it's a function that's able to set the value of a different field in the form. In this case, the slug. Now there are quite a few of these hook methods like afterStateUpdated within the filament codebase. However, it's not just those hook methods that are able to accept a function like this.

Dynamic closures in config1:33

codebase. However, it's not just those hook methods that are able to accept a function like this. Pretty much every single configuration method within all filament components accepts a function. For example, let's pass a label in here. And this also accepts a function. We can return our new name from here and this function's going to get run when we render the form. As you can see, the new name is now in the form. We can also make this dynamic since it is being re-rendered each time the field is blurred. So for example, let's pass a random string in here so we can see it updating.

We can also make this dynamic since it is being re-rendered each time the field is blurred. So for example, let's pass a random string in here so we can see it updating. And blur. As you can see, that string changed. We're also able to inject utilities into each of these functions very similarly to this after state updated. For example, we can get the state of the name and pass it here. Now let's return the state. And as we type, the label updates with the state of the current field. There are many options for utility injection in form components and they can be found in

Available utility injection2:40

And as we type, the label updates with the state of the current field. There are many options for utility injection in form components and they can be found in the filament documentation. State we've just discovered. Component is the current component instance, so in this case it could be a text input. This is useful for being able to access configuration from within these functions. Also you have direct access to the Livewire component that this field has been mounted to, as well as the record that you're editing, if you're editing one. In this case we're not. You can get the value of a different field.

How Filament evaluates closures3:12

In this case we're not. You can get the value of a different field. And you can also set the value of a different field, like we're doing in our case. We also have the operation, which we've just met as well. Multiple utilities can be injected into one function and it doesn't matter which order they are injected in because Filament is able to resolve them based on their name. You're also able to inject dependencies from Laravel's container in these functions. So let's have a look into the Filament codebase to see how this is actually achieved. So when we set the label, we're accepting a string, a closure. Now if the label is set to a closure, then it's stored here, like normal, but evaluated.

So when we set the label, we're accepting a string, a closure. Now if the label is set to a closure, then it's stored here, like normal, but evaluated in a very different way. So in the getLabel method, we're passing it to this evaluate. And this is a helper within the Filament core that's able to check if the value is a function or not, and if it is, call it, and if it's not, just return the label as normal. So where do we actually pass in the state, operation, LivewireComponent, record? So resolve, default, closure dependency by name. In this case, we're looking for Form Components. Here's where we pass everything in.

In this case, we're looking for Form Components. Here's where we pass everything in. This means that for every function that we evaluate on behalf of a Form Component, these sorts of utilities are injected, but you can also inject utilities just for one configuration method. So for example, when we call the afterStateUpdated function, we do also pass in the oldState as well as the newState, and this wouldn't really be appropriate for any of the other functions, and that's why it's not a default evaluation parameter. So let's take the TextInputComponent that we built in the last episode and add some evaluation to it.

Wrapping custom input in Livewire4:59

So let's take the TextInputComponent that we built in the last episode and add some evaluation to it. First we need to actually connect it to Livewire, because at the moment it's just being rendered by a static Blade view. So if we go into web.php, we're going to be replacing this with a LivewireComponent. Let's make a new one, php artisan make:livewire TestForm. Now I'm going to go into the TestFormComponent, and we can pass in the input to the render function very similar to how we did it in the root. Let's pass it into the view. Now we can actually get rid of this function altogether and replace it with the TestForm.

Let's pass it into the view. Now we can actually get rid of this function altogether and replace it with the TestForm. In the view, we now need to render this input. And now this looks exactly the same as how it was, but it's actually wrapped in a LivewireComponent. Now we want the form to react to something that's typed into the field. We need a Livewire property where we can store the value of the field, so let's create that. Let's go into the TextInput and make this wire:model, and then the name of the input. We need to create this getName method, so TextInput, and let's create a new method called public function getName, where we're just going to be returning the name. Now let's go back into the browser and inspect the input.

public function getName, where we're just going to be returning the name. Now let's go back into the browser and inspect the input. As you can see, it now has a wire:model matching the name of the field. If we change this to be wire:model.live, then each time we type into it, the network requests are being made and the form is being re-rendered. And this is going to allow us to do something like changing the label each time the user types something into the field. Let's pass in a function to the label method here, so function, and just to check that it's actually dynamic, we're going to be returning a string, random. In our TextInput, currently the label method only accepts a string, so we need to make

Implementing evaluate and injection7:24

it's actually dynamic, we're going to be returning a string, random. In our TextInput, currently the label method only accepts a string, so we need to make sure that it also accepts a closure. And when we store it, that should also accept a closure. In the getLabel method, this is where we're going to be running that closure. So first it's going to be checked if it's a closure or not, and if it is, it will be evaluated. So in the public function evaluate method, we're going to be accepting a value here and we can return it. Now if the value is an instance of closure, then we want to run the value and return it.

we can return it. Now if the value is an instance of closure, then we want to run the value and return it. We can make use of this evaluate method here now, so this evaluate, this label, and if it's not set yet, we're just going to pass in null. Now when we type, the label is being regenerated and it's being re-rendered since it's live. The next part of this is being able to inject utilities into this closure. The easiest way to achieve this is with Laravel's app call method. So if we replace this simple function call with app call, and then pass in value there, it should work exactly the same. However, we're now able to pass in utilities into this closure.

it should work exactly the same. However, we're now able to pass in utilities into this closure. So let's pass an array, and the keys of the array are the names of the parameters that we're going to be injecting. So for example, random, we could inject a random string. And now if we go into the text input that we've defined, we can accept a random here and return it. And Laravel is dynamically injecting that value into the field. We can also add a different one, so foo. And it doesn't matter which order we put these parameters in, they will be passed in correctly.

We can also add a different one, so foo. And it doesn't matter which order we put these parameters in, they will be passed in correctly based on what their name is. In Filament, we aren't actually using the app call method directly from Laravel. This is because some of our evaluation is much more advanced than just passing in a parameter based on its name. We are also able to resolve parameters based on their type, for example, which Laravel is not able to do. But this is a great example of how utility injection in Filament works, and how you can make use of it to build dynamic forms.

But this is a great example of how utility injection in Filament works, and how you can make use of it to build dynamic forms. Now let's try something a bit more tricky, and try and get the current value of the field and pass it into the label. So for this, since we're using the Livewire component to store the field's value, we actually need to be able to access the Livewire component itself. So here, I'm going to create a new method, and I'm going to call it Livewire. Now in Filament, components have Livewire available already, and they automatically inject the current component into them, but in this case we don't have that yet. So let's pass in the Livewire component manually.

inject the current component into them, but in this case we don't have that yet. So let's pass in the Livewire component manually. Let's now accept the Livewire component, so public function livewire(). This is going to accept Livewire component. And we're going to return this, so it's chainable. And we can set the Livewire component inside this property. So protected, component, Livewire. Now that we're able to store it, we can now access the current value of the field within the evaluate method. So here, let's pass in the state, so we can use this, Livewire, and the current field.

the evaluate method. So here, let's pass in the state, so we can use this, Livewire, and the current field name which is from the getName method. We should now be able to access the state in here, so state, and let's return the state from the label. New state, perfect.

The reasons why function evaluation is useful when building dynamic interfaces. Allowing setters to accept functions as arguments as well as static values. Using Laravel's <code>app()-&gt;call()</code> method to call functions. Dynamically exposing utilities to functions during evaluation.

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