Adding Create Route0:00
Now that we're technically able to store a new Post in our database, we need to allow the user to see a form that will submit that request. I've created the createTest.php file here already. Here's our requires authentication check. Let's run it and see what happens. The root doesn't exist yet. This should be as simple as adding create to the only method inside our root resource here. If we rerun the test, now it passes. That is how easy root resources are. Another reason you should stick to the defaults. The next test we have is it returns the correct component. So, let's log in as a User, acting as userFactory::create(). And once we're logged in, we can make that get request to route('post.create'). And then we made that macro, didn't we? AssertComponent. So, we should be able to call that. AssertComponent('posts/create'). Okay, let's run this test. It says not a valid Inertia response, which I would very much expect because we've not actually, at the moment, returned anything from the create method inside our PostController. So, let's say return inertia() and we can return posts/create. Rerun the test.
Returning Inertia View1:11
At the moment, returned anything from the create method inside our PostController. So, let's say return inertia and we can return post/create. Rerun the test. Now it says that file doesn't exist. Again, another fairly simple fix. We'll go to resources/js/pages/posts. And let's copy the show.view page because a lot of the layout will be the same. We'll call it create.view. Rerun our test and we're off to the races. Let's make edits to our view file so that we actually see a form on the front end that we can submit. And I'm going to start in the script section this time. I'm going to remove the original because it's so far away from what we actually need. So, we'll have a new script set up and we need an inertia form that we can keep track of. So, we'll say const form = useForm and the properties that we're going to be passing to the back end are the title property and the body property. So, let's add those in now. Then we need a way to submit this form.
Setting Up Inertia Form1:59
So, we'll say const form equals useForm and the properties that we're going to be passing to the back end are the title property and the body property. So, let's add those in now. Then we need a way to submit this form. So, let's have another const and we'll call this createPost. And createPost is a closure that is going to take the form, make a POST request to the correct route, and we know that that route is posts.store. And that should be all it needs to do. Everything else should just work. So, now we can go ahead and wire this up to our front end. Let's change the title here to create a post. And we can add the same thing to our browser title up here instead of the post title. So, create a post and we can get rid of the span. That's no longer needed. Let's introduce a form element and the form is going to wait for submit, prevent that submit from happening, and then finally call the createPost method. Brilliant.
Building Form UI2:51
Let's introduce a form element and the form is going to wait for submit, prevent that submit from happening, and then finally call the createPost method. Brilliant. Now, we need a few divs here. We need a div that will store the title, we need a div that will store the body, and then we need a div that will store our actions. We'll add our action in first. That's going to be a primary button. The type is submit because we need it to submit this form. And the text of the button could just be create post. Inside this first div, well, we're going to need a label. So, we'll add our input label. It's going to be for a title and the text will just be title. I don't actually think we need to see this. It's going to be very obvious. So, again, I'm going to add that sroOnly class so that only screen readers see the input label.
I don't actually think we need to see this. It's going to be very obvious. So, again, I'm going to add that SROnly class so that only screen readers see the input label. Let's then add a text input. Let's give it an ID of title to link the input and the label together. We'll add a class of width-full so that it fills the full length of the screen. We want a v-model on here of the form.title attribute. And let's have a placeholder as well. So, the placeholder for text input is going to be give it a great title. And let's use a little ellipsis there for visual flair. And then finally, we want our error, right? So, our input error. And the message is going to be form.errors.title if there is an actual error for the title. And finally, we'll give it a class of MT1 to visually space it out just a little bit.
And the message is going to be form.errors.title if there is an actual error for the title. And finally, we'll give it a class of mt-1 to visually space it out just a little bit. Okay, that should be everything for our title. Let's copy that and paste it down here ready for our body. So, the first thing I'll do is go ahead and select all instances of title and change it with body. This is going to also be body. And let's change this for textarea. That makes more sense. I don't think we need to specify width-full because that's the default for a textarea. We don't want a placeholder. It's very obvious what it's going to be for. But let's give it 25 rows, for example, so that you can have a nice chunk of space to write up to 10,000 characters inside your post. Let's get rid of the article here and get rid of the comments here as well. We don't need them. Jump into our browser. We'll manually go to /create. There we go. We have a form.
Testing Submission and Validation5:09
Let's get rid of the article here and get rid of the comments here as well. We don't need them. Jump into our browser. We'll manually go to /create. There we go. We have a form. It needs some spacing. We can easily fix that. So, let's go ahead and maybe use mt-6 here. And then maybe on this div and this div, we can add a class of mt-3. Yeah, that's pretty nice, isn't it? Straight away, we should be able to click Create Post and see the validation errors coming back, which we can, which means that it is wired up to the correct form. Let's go ahead, fulfill the validation requirements, and see if we can create our very first post. So, rather than type this out manually, I'm going to use a little plugin for Raycast called Lorem Ipsum and generate a sentence of Lorem Ipsum for our title. And then for the body, I'll do the same thing, but I'm going to generate paragraphs of Lorem Ipsum.
and generate a sentence of Lorem Ipsum for our title. And then for the body, I'll do the same thing, but I'm going to generate paragraphs of Lorem Ipsum. And that means I don't have to type anything out manually. Hit create post, and would you look at that? Here is our newly created post on the show page. It's pretty cool that we're able to build out the store and create routes so quickly for features like this. Obviously, it's missing things that we're going to add in subsequent episodes, but the fact that we're able to scaffold this out and use TDD at the same time, it's not like we've just been throwing things at the screen and seeing what sticks. We followed a strict pattern of TDD. We could refactor whatever we wanted to here. It still only takes 10 or 15 minutes to put something like this together.
Reflecting on TDD6:34
We followed a strict pattern of TDD. We could refactor whatever we wanted to here. It still only takes 10 or 15 minutes to put something like this together. Crazy how powerful the Laravel toolset is. Okay, let's go ahead and make this even better than it currently is.
