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

Problem: Reusing Forms0:00

This next question comes from Mason via email, and he asks, how do I reuse my form HTML for create and edit actions, where each one requires unique form attributes and submit button text? Okay, so do you understand what he's saying here? Imagine you need a form to, in this case we have like a little blog here, you need a form to create a new Post, right? Okay, so maybe you would go to /post/create, and we'll create that in a moment. But as you can imagine, the HTML for that new blog post is going to be virtually identical to the HTML for editing the blog post. So what Mason is asking here is how do we dry that up as much as we can,

is going to be virtually identical to the HTML for editing the blog post. So what Mason is asking here is how do we dry that up as much as we can, while knowing that, for example, the create forms action will be different than the edit forms action, and then maybe the edit form submit button will be different from the create form submission button. So how do we make it a little dynamic while still reusing the code? Okay, I'm going to show you that in this episode. So take a look at what I have here so far. Like I said, I just whipped up a very, very quick blog. So we have a route to posts, we fetch our posts, and we load posts.index. If we take a look at that, we filter through the posts,

Review Existing Routes1:03

So we have a route to posts, we fetch our posts, and we load posts.index. If we take a look at that, we filter through the posts, and for each one we display an article with the title and the body. And that gives you this. Okay, next we have post/{id} wildcard. We use Laravel's implicit model binding here, or route model binding to automatically fetch the post, and we pass that to post.show. Now in that one, we just have an article and then a link to go back to the main posts section. All right, very, very simple stuff. So now we're going to add a new section to create a post.

Build Create Post Form1:38

All right, very, very simple stuff. So now we're going to add a new section to create a post. So we'll say Route::get('post/create'), and then here we will return a view post.create. All right, let's create it. resources/views/posts/create.blade.php. And I'm going to take some of the HTML from the index page. All right, we extend the layout file. All that is is just wrapping HTML. Nothing fancy there. Okay, so here, yeah, we're going to set up a form, right?

Nothing fancy there. Okay, so here, yeah, we're going to set up a form, right? And by the way, regardless of your editor, set up little snippets that will do this kind of junk for you. It's going to save you so much time. So yeah, we create a Post. So the method will be POST. The action will be posts. If we're using basic RESTful conventions, we do want a csrf field for virtually any form you will submit.

If we're using basic RESTful conventions, we do want a CSRF field for virtually any form you will submit. The method field, that's irrelevant in this case. You would only do that if you're going to use one of the request types that browsers don't officially support. In this case, post is supported. And then finally, our button is submit. So now, yeah, what are we going to have here? We're going to have a text field. The name will be title.

We're going to have a text field. The name will be title. And we're doing this very quickly. The title of your post. And then we'll do a text area here where the placeholder is the body for your post. And let's see, the name would be body, right? Okay, so let's wrap these within divs just to give us some spacing here. And let's see what we got here. So post/create.

Fix Route Wildcard Order3:05

And let's see what we got here. So post/create. So it's trying to find a post. Let's come back to our routes file. And yeah, of course, you always want to be careful that your wildcard is above these hardcoded values. In this case, that would pick up anything, including post/create. That's a common mistake. So let's give it a refresh, and we'll see our terrible looking form. But this will be okay.

So let's give it a refresh, and we'll see our terrible looking form. But this will be okay. Create a new post. Actually, no, it's not going to be okay. We can't look at that all this time. Let me pull in a quick CSS framework. It'll take 30 seconds. Lately, I've been using this CSS framework called Bulma, which is really cool. So let's just grab that. Come back to Sublime.

So let's just grab that. Come back to Sublime. Let's go to our layouts file. And we'll link to that. And we can get rid of this stuff. Okay, let's see what that gives us. Come back and refresh. And a little bit. But next, we can style this form by doing this. We're going to give these a class of control.

But next, we can style this form by doing this. We're going to give these a class of control. And then here, we'll give this a class of input. And then down here, a class of textarea. And generally, that's going to set the width accordingly and make it take up all the available space. And the control class will apply some arch and bottom. Yeah, just a little bit better. And I think that'll be fine for our needs. Class title is one.

And I think that'll be fine for our needs. Class title is one. Bulma is pretty cool. You should check it out. Anyway, so we have a basic form here. No problem at all. So when we submit it, we've decided that it will submit to /posts. And real quick, by the way, let's give that a class of button is primary. Yeah. OK, but anyways, that means we need to set up an endpoint for /posts.

Yeah. OK, but anyways, that means we need to set up a endpoint for /posts. And at this point, you probably want to use a controller, by the way. Route, when we submit a POST request to posts, this is where we will update the form. And forgive me, but let's skip the validation portion. So post, create a new one using the data from the request. But yeah, in real life, add some validation. And we will return to let's return a redirect to /posts. All right.

And we will return to let's return a redirect to /posts. All right. Does that make sense? We submit the form. We just do a quick post create. And on that note, we should specify our fillable fields. title and the body is all I have here. Anyways, we create the post and we redirect back to our overview section. So if I were to say my new post, the body, submit, it looks like we need to add some CSS.

So if I were to say my new Post, the body, submit, it looks like we need to add some CSS. But sure enough, we can see that there. Let's do that real quick. post/index. And we'll say, let's give it a class of box, refresh. And then let's give it a title. Class title is two. Refresh. Way too much, is four.

Refresh. Way too much, is four. And that's good enough for me. OK, so this is working. We have a form to create a Post. But now we want to form to edit an existing Post. And the URI will take the shape of something like this. OK, well, let's do that now. And we'll see how this goes. So Route::get('post/{id}/edit').

And we'll see how this goes. So Route::get post/{id}/edit that will accept the Post. And then once again, we will return a view to edit the Post. And then we'll pass it through. OK, so here's where we will hit a small little roadblock. post/edit.blade.php. And let's just steal what we have up here, like so. All right. And so we'll say, edit Post.

Extract Form Partial6:34

All right. And so we'll say, edit post. And if I came back and gave this a refresh, yes, we can see it here. But we are duplicating the form. So now your instinct might be, well, Jeff, this is really easy. All you have to do is take your form code and extract it to a partial. So something like resources/views/posts. And then some people use an underscore at the beginning to represent a partial. You'll see the same thing with Sass. It's up to you.

You'll see the same thing with SAS. It's up to you. These days, I don't do it quite as much. So we'll just call it form and paste it in there. So yeah, a lot of people would say this is all you need to do. But no, we still need to make a couple tweaks here. So let's get rid of that. Include post.form. And if we were to come back, sure enough, it's still going to work. So that means we should be able to do the exact same thing to the create view, right?

And if we were to come back, sure enough, it's still going to work. So that means we should be able to do the exact same thing to the create view, right? Grab all of that, paste it in, refresh. I'm sorry, go to /post/create. And yes, we have removed the duplication. And if it was just that, there'd be no problem. But as we know, in real life, this button may be different for the create page versus the edit page. And also, we know that if you're editing a Post, well, we need to populate these inputs with their current values.

And also, we know that if you're editing a Post, well, we need to populate these inputs with their current values. So let's go back and keep working on it. Now, we already know that the form's action attribute will be different, whether it's creating or updating. So yeah, you could do this dynamically and try to build it up. But I always think that gets kind of messy. So what I like to do is I take the form wrapper itself, and I keep them in their respective views like this. All right.

views like this. All right. So now this is totally fine. Come back. This can all leave. And now our form code itself is a little more reusable. So that means we can come here, do the same thing. form method is post. The action will be post slash and then the post id, right? Close that out.

The action will be post slash and then the post ID, right? Close that out. And then we'll set the method field. OK, so now anything that is unique to this particular form can be stored here. And that way, we don't have to dynamically figure it out. I think this is cleaner. So our create page will post to slash /posts, and our edit page will patch or really post and then tell Laravel that it's a patch request to this endpoint. OK, so now if we come back, everything should still work the way it did before. But the form tag itself is dynamic.

Make Fields Dynamic8:57

OK, so now if we come back, everything should still work the way it did before. But the form tag itself is dynamic. Next, we have two more things. We need to make the submit button dynamic, and we need to populate the inputs for the edit page. OK, well, here's what we could do. Right now, our button is very generic, but it might be something like create post or update post, right? So create post, but we're on the edit page. That doesn't work.

So create Post, but we're on the edit page. That doesn't work. OK, so here's what we could do. We could say submit button text, or if you're using php 7, you can use this, or we could say create Post. That will be our default. OK, so if I come back and give this a refresh, once again, post/create, we have our default. But now, when we edit a page, we should override that. So we can do that by passing in values here.

But now, when we edit a page, we should override that. So we can do that by passing in values here. So in this case, I want the submit button text to be update post. OK, so now we're just introducing small little sections that should be dynamic. Post create, Post edit. All right, next, I want to see the contents of each of the fields here. So we could do something like this. To start, I like to do things where I put these on their own line, and I'll do the same here. Anyways, yes, we could set the value here, and I could say the postTitle as a first.

here. Anyways, yes, we could set the value here, and I could say the post title as a first step. Let's see. post body. And if I were to come back and refresh, yes, we see it there. But what if there is a validation issue? Well, when we redirect back from our controller, we probably want to make sure that we grab the old value. So you could always do something like give me the old title if it exists.

the old value. So you could always do something like give me the old title if it exists. Otherwise, default to what we have in the database. And we could do the same thing here. OK, so now we're still going to see the value. But if we do redirect back with the input and with any potential errors, these inputs will refer to their last values that you submitted. OK, so this is all great. But now we have a problem. We go back to post/create, and the post variable doesn't exist.

But now we have a problem. We go back to post/create, and the post variable doesn't exist. And this is what confuses a lot of people. But really, this is an easy fix. All you'd have to do is this. Let's just pass through an empty post. And you can almost think of it like a null post. So we're going to send it a new App\Post. And that way, within the form, yes, we can respond to post title and post body. But of course, nothing will be returned.

And that way, within the form, yes, we can respond to postTitle and postBody. But of course, nothing will be returned. So that means if I give this a refresh, we have our form here. And it will submit to the proper location. CreatePost. There we go. But we can edit a Post. And that will submit to the proper location as well. And mostly, that does it for this lesson. If you want to stick around, I'm going to finish up by moving all of this into a Controller.

Move Logic to Controller11:44

And mostly, that does it for this lesson. If you want to stick around, I'm going to finish up by moving all of this into a controller. But more or less, we're done for the video. So you can stop watching if you want. OK, so I'm going to php artisan make:controller. I'm going to call it PostController. And I'm just going to slowly move all of this over. And yeah, in this case, we really have a resource. So you know what? I'm going to delete that and do it again.

So you know what? I'm going to delete that and do it again. But add the --resource option. And that'll give me some boilerplate to get started. OK, so if we go to all posts, this is what I want. Let's get rid of that. Pull this at the top. Next, what do we have here? A form to create a Post. All right, you're dead.

A form to create a Post. All right, you're dead. Next, we have a page to show the Post. Right there. Let's make sure we accept the Post. All right, so show, create. And by the way, you could also do this. You could say right here, $post will be new Post. Now, in your create view, you could just pass this through or do our little compact trick. And that'll give you an array.

Now, in your create view, you could just pass this through or do our little compact trick. And that'll give you an array. Either one works. OK, next, what do we have? That guy's done. This is to create the Post or to store the Post. And why don't we defer to request()->all() here. All right, and then one other to edit the Post. All right, and once again, accept the Post. Like so.

All right, and once again, accept the post. Like so. So now, let's go ahead and build up a full resource here. And see how we're doing. OK, all of my posts. Here's a specific post, unstyled. But I can edit the post as well. Or I can create a brand new post. So now, if we wanted to add a method to update the post, yeah, let's validate it. Let's validate the request.

Update Validation and Old Input13:51

So now, if we wanted to add a method to update the Post, yeah, let's validate it. Let's validate the request. And specifically, I want a title and a body here. Next, we're going to track down the Post using the route model binding again. And we'll just say post->update with the request data. And then finally, return a redirect to post slash the post ID. OK, let's see if I made any mistake. So we'll say updated. And there we go. It works.

And there we go. It works. But now, yeah, we can see the old text. So in real life, you would have, like I would recommend, adding the required attribute to all of your inputs or your text areas. So that way, if you try to submit the form, but you leave the input blank, it's going to make you fill that out. So check it out. Imagine that the user submits the form. And we want to say, you need to give us at least three characters for the body.

Imagine that the user submits the form. And we want to say, you need to give us at least three characters for the body for us to consider it valid. But you don't do that. You just give us two characters. OK, we update the post. It does redirect back. We're not displaying the errors. But what I want you to see here is that because we checked for the old text, it does display that rather than what is stored in the database.

But what I want you to see here is that because we checked for the old text, it does display that rather than what is stored in the database. And again, we get that because of this little number right here or right here. So yeah, if you didn't do that and you only use two characters, well, when you redirect back, it's just going to default to what's in the database rather than what you typed in. So this is a good way to go about it. Give me the old value if we have it in the session. Otherwise, default to the post title. All right.

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