Introducing Article Forms0:00
Forms are one of the most important things that we work with inside of our applications, because it's the primary way that we get information from the user. And I know that we have talked about forms before, but we need to spend a little more time. Because Livewire has a lot of wonderful features when it comes to working with forms, especially forms that are very similar to each other, like the creating form and the editing form. And I want to add that functionality to our application. I want a link to take us to a create form for creating articles, and I want to add an edit link to edit articles. So let's start by going to the article list view, and I want to paste in the link for
Create Route and Component0:42
edit link to edit articles. So let's start by going to the article list view, and I want to paste in the link for our create form. The href points to dashboard/articles/create, and I'm using the wire:navigate attribute so that it will navigate us like it would in a single page application. And of course, before we can navigate there, we need the CreateArticle component. So let's create that component. And let's go ahead and open up our route file so that we can define the route for that link. And let's see, that was articles/create. That's going to point to the CreateArticle component.
And let's see, that was article/create. That's going to point to the createArticle component. And let's open up createArticle, because we already kind of know what we are going to be working with. We have the title, and we also have the content. And we can go ahead and set up the validation rules here. So let's do that using the validate attribute. And I think all that we really need is required. Ideally, we would have like a minimum length. But for our purposes, this is going to be just fine.
Saving New Articles1:45
Ideally, we would have like a minimum length. But for our purposes, this is going to be just fine. And since we're here, we can go ahead and write a method to save our data. So the first thing we want to do is validate our data so that then we can use our Article model to create. And we could just pass in all of our component data. That title and the content would be there. And then we would want to redirect back to the dashboard article list. Now, that would be fine, but there is a navigate option. And if we set this to true,
Now, that would be fine, but there is a navigate option. And if we set this to true, then it's just like we used the wire:navigate attribute, except that we are redirecting in that case. Now, I don't think we did anything as far as the fillable property. Yes, we did not. So inside of our Article, we need to set fillable to an array of title and content. And that's going to be fine. So we have that set up.
And that's going to be fine. So we have that set up. We just need our view. So let's open up the create article view. And I'm gonna paste this in because I don't want to see me type this. You don't want to see me type this in. And there's really nothing spectacular about it. I mean, it's just a normal form. We have two fields, title and content. Although we do need to change our base component class to AdminComponent.
We have two fields, title and content. Although we do need to change our base component class to AdminComponent. That way we get our nav bar. Yes, great. Okay, so we have an input element, which is bound to our title property. We have the validation error for that. Then we have a text area that's bound to our content property, and a validation error for that. We have our save button, and we are using the wire:submit action to call the save method on our component class.
We have our save button, and we are using the wire:submit action to call the save method on our component class. So everything should work. If I click on Save, we see our validation errors. So let's have a test title and some test content. And now let's save it. That redirects us. We can scroll all the way down, and voila, we have our test title. Now, as you well know, there are a lot of similarities between creating and editing.
Adding Edit Functionality3:49
Now, as you well know, there are a lot of similarities between creating and editing. So let's implement the edit functionality. And it's going to entail a lot of copying and pasting. We first of all need the edit article component. So let's go ahead and create that inside of our web.php file. Let's set up the route for the edit article component, except that the URL needs to be a little bit different. We'll have dashboard/articles. Then we would have the article that we want to work with, and then slash edit.
We'll have dashboard/articles. Then we would have the article that we want to work with, and then /edit. And we are done with our route file, so we can close that. Let's go to our article list, because we need a link inside of our list, so that we can go to the edit view. Let's take our button, and let's copy that. And this is a link, so we need to change it to an a element. The text, let's change from delete to edit. We don't need wire:click or wire:confirm, but we do need wire:navigate. So let's add that.
We don't need wire:click or wire:confirm, but we do need wire:navigate. So let's add that. We don't need a background color, so let's get rid of that, as well as the rounded corners. And then finally, we have the href, which will go to dashboard, articles. Then we will have the article_id, followed by edit. And yeah, that should work. So if we click on the edit link here, that takes us to our edit page. Of course, we need to make some changes, such as our base class. I think we're done with ArticleList, so let's close that.
Of course, we need to make some changes, such as our base class. I think we're done with ArticleList, so let's close that. Let's open up EditArticle and the edit article view. So our EditArticle component will need to inherit the Admin component. And for the most part, we can just take most of everything from our CreateArticle class. We don't need render because EditArticle needs its own render method, but we can paste in those properties. We need the validate attribute, but here we are editing. We are going to be getting an Article to work with.
We need the validate attribute, but here we are editing. We are going to be getting an article to work with. So let's use the mount hook to where we will get our article that we will then use to set the title to the article title. We'll do the same thing for the content. And you know what? We should also just have a public article, and we'll just call it article. So that we would have a reference to that, and we would be able to use that in order to update our data. So inside of save, we still want to validate our data, but we're not creating.
we would be able to use that in order to update our data. So inside of save, we still want to validate our data, but we're not creating. Instead, we are using this article we will call update. We can pass in, really, we just only need the title and the content. And then we still want to redirect. So yeah, that should work just fine. But then we need to do something with the view. So let's just take what we have for the create view and paste that into the edit. Because for the most part, it is all the same. Our title is going to be different.
Because for the most part, it is all the same. Our title is going to be different. It will be editArticle, but our input is still bound to the title. textarea is still bound to the content. We still want to call save. Yeah, everything should be the same. So if we change our title and save it, we should see that reflected in our list. And we do, and that's great. It works, and there's something to say about code that works. I think I say that a lot.
Refactoring with Form Objects7:00
It works, and there's something to say about code that works. I think I say that a lot. Working code is fantastic, but we want to make this a little bit better, because we did do a lot of duplication. And ideally, we would extract a lot of the similar functionality into a separate class to essentially simplify the code inside of our components. And Livewire has a feature called a form object for that purpose. We'll call it ArticleForm. And you can see that it creates a file inside of app/Livewire/Forms. And the whole idea is to just extract all of the form specific stuff.
And you can see that it creates a file inside of app/Livewire forms. And the whole idea is to just extract all of the form specific stuff inside of this class. So that our CreateArticle and our EditArticle components will be nice and lean. So it's going to look something like this. We're going to take out these methods here. And we will have an ArticleForm object, which we'll just call form. We'll have a save method. So that all we would need to do is use our form object. We'll define a method called store.
So that all we would need to do is use our form object. We'll define a method called store. And then we will simply redirect like we did before. I should have taken all of that code out, but oh well. And we redirect to dashboard/articles. And we want to use the navigate feature. So for our create article, that's what this is going to look like. So inside of our ArticleForm class, we'll paste in that stuff. We want our title and our content. We have the validate attributes still there.
We want our title and our content. We have the validate attributes still there. But for our save method, let's rename that to store. So that we will validate this data. We will save, or rather we will create our new article. And that's it. We don't really need to do anything else. So then we can turn our attention to the edit article component. And again, we do something similar. We start to take out or extract the similar data.
And again, we do something similar. We start to take out or extract the similar data. In this case, we need to extract this article object. Let's put that inside of our articleForm. And then we essentially need to do the same thing that we did inside of our mount method here. But we don't have these properties anymore. Instead, we have that public articleForm. So that's inside of mount, we can use our form object. We could have, you know, something similar to mount. But let's not call it mount.
We could have, you know, something similar to mount. But let's not call it mount. Let's call it setArticle. And then we will pass in that article. And that's really all that we need to do there. So that inside of our article form, we can go ahead and implement that. It was setArticle. We accept the article that we want to work with. And then we just set the title, the content, and our article object. So that now inside of editArticle, whenever we call save, we don't need to validate.
And then we just set the title, the content, and our article object. So that now inside of editArticle, whenever we call save, we don't need to validate. We don't need to update. Instead, we could once again use our form. We could call an update method. And then that would do everything else. So once again, we go back to our article form. And we define that update method to where, once again, we validate. And then we update the provided article. But you know what?
And then we update the provided article. But you know what? Let's call only up here for the store method. So now all of the functionality for working with our article form is here inside of this form class. And then the components displaying those forms simply use that articleForm object. And then save the form data. Now, this does mean that inside of our views, we need to change where we bind our models. So we have form.title and form.content.
we need to change where we bind our models. So we have form.title and form.content. We need to do the same thing inside of the edit view, form.title and form.content. But we are almost to a point that we could use the same exact view for both create and edit. I'm not going to do that because, well, yes, we have essentially duplicated the same form. I know that there have been many times that I wished, oh, I wish I had two different forms. So we'll keep this as is.
oh, I wish I had two different forms. So we'll keep this as is. But now we can go back. Let's go ahead and let's delete this. And let's create a new Article. So here we will have testTitle for form object. And then this is the content. Whenever we save, everything should be fine. We can scroll to the bottom. There is our article.
We can scroll to the bottom. There is our article. We can edit that article. The data is loaded. Let's edit our title and then save it. And hopefully, everything should work. And sure enough, it does. So Livewire's form object is very useful when working with forms, especially if you have multiple forms and those forms are similar to one another. Because they allow us to extract the form functionality inside of its own class.
especially if you have multiple forms and those forms are similar to one another. Because they allow us to extract the form functionality inside of its own class. So that everything that uses that form is nice and clean. It doesn't have to worry about the validation or creating records or updating records. It's fantastic and it makes us much more productive.
