Auth-Gated Create UI0:00
Okay, let's work on creating ideas. So I want to make sure that the User is logged in before they can perform this action. So let's start there. So let's go to our app, Blade, I believe it's in there. And we have this text here. So let's change this text based on if they're logged in or not. So let's use the auth directive. And we can also use else here. So this case right here is if they're logged in. But if not, let's say, please log in to create an idea.
So this case right here is if they're logged in. But if not, let's say, please log in to create an Idea. Okay. So now since we're not logged in, we should see that text. Okay. So let's do the same thing for the form. If they are logged in, show the form. But if not, show a login button. So we can do the same thing here. Let's say auth and endAuth.
So we can do the same thing here. Let's say auth and endAuth. And we'll grab the form and put it in there for the auth case. But we can also have an else case for the button. So let's do that. So let's put it in a div, say my-6, and let's make it centered. And just have two links in here that link to the login or the register routes. So I'm just going to grab the buttons from here. So these ones, but just make it a link. So this would be a blue button.
But for now, I'm okay with just repeating, maybe we'll do that later on. So let's make another button here or another link. And we don't need this SVG, and it's not a button, it's a link. And the link is to route('register'). So let's say route register. And I don't think we need this. And we can also get rid of this span and just say sign up. Okay. sign up. See how that looks.
Create Livewire Component3:26
So let me just make a new User here. Let's go ahead and register and this should log us in as well. Okay. And the form is back. So let's work on the actual functionality of creating an Idea now. And like I said, I'm going to be making use of Livewire for this. It's not really necessary, but Livewire does add some nice features like disabling the button when you submit. And you can do things like real time validation if you want to do that. So let's make a Livewire component.
And you can do things like real time validation if you want to do that. So let's make a Livewire component. php artisan make:livewire Let's call it CreateIdea. Okay. And let's first move everything in the form. So everything in the auth directive here, let's grab this and let's put it in Livewire CreateIdea. Okay. So let's open that up.
Okay. So let's open that up. Create Idea. And let's paste that in. Make sure to re-indent. And this should still render like before. Okay. Let's open up the CreateIdea class. And let's add some state here. So what do we need?
Bind Form State4:42
And let's add some state here. So what do we need? So if you take a look at our form, we have three fields. We have a title, a category, and a description. So let's start with that. So it's a public title. So I have one for a category and it's default the category to 1 because that's the first one selected here. And it's a description. Okay.
And it's a description. Okay. So let's save that and let's go to our form again. And let's add the action we want to perform here. So let's say wire:submit, and let's prevent the default action. And let's call a method called createIdea, which we'll create in a second. And let's add the wire:model on those fields. So the first one is the title. So this is this one here. So let's put it first, actually say wire:model, and I'm going to use defer.
So this is this one here. So let's put it first, actually say wire:model, and I'm going to use defer. So it doesn't make any requests until we hit the submit button. Okay. And let's do the same for the others. So let's add it for the select right here. And this one would be category. So it's going to update these values. Actually we have to grab these values from our categories table. So let's do that.
Load Categories Dynamically6:02
Actually we have to grab these values from our categories table. So let's do that. Let me add the wire:model first on this one. So wire:model.defer equals description. So now let's add the categories here. So I'm going to loop over them, and we'll pass them in in a second. But since we're in the view already, we can work on it here, say foreach. And we'll grab the categories as category. Let's put this up. And the value is going to be the ID of the category.
Let's put this up. And the value is going to be the ID of the category. So this is what's going to be stored in the database. So that's going to be the category ID. And the thing that shows up in the select box is the name. So say category name. Okay. And to grab the categories, we can pass them in through the controller if you want. So in our IdeaController, we can pass it through here and then pass it to our Livewire component, or we can just grab it directly from the Livewire component.
So in our IdeaController, we can pass it through here and then pass it to our Livewire component, or we can just grab it directly from the Livewire component. So let's take that route. Great idea. And we can just grab it from here. So let's just say categories, and we can just say Category::all(). Okay. Let's import Category. And hopefully this works. So let's see if it's grabbing the categories from our database.
And hopefully this works. So let's see if it's grabbing the categories from our database. So right now this is hard coded, but if I refresh, it should grab them from the database. And it looks like it does. Cool. Okay. Now we can work on the createIdea. So let's work on that. So remember, I added this wire:submit.prevent, and we're calling a createIdea method on the class.
Implement Idea Creation7:53
So remember, I added this wire:submit.prevent, and we're calling a createIdea method on the class. So let's do that. Let's add it here. Let's say createIdea. And let's go ahead and create that idea. So we have Idea::create. So what does an Idea need? So if we look at our database, it needs a user_id, category_id, status_id, title, and description.
So if we look at our database, it needs a user_id, category_id, status_id, title, and description. So user_id is going to be the logged in user, auth_id. Okay. And also we should wrap this in a auth check to make sure the user is logged in. So let's do that as well. So if auth check, then perform this action. But if not, then we can just abort. And what's 403? I believe it's forbidden.
And what's 403? I believe it's forbidden. Now we can do response. I believe there are constants here. So let me import the response. I believe it's on the Symfony Response. So let's go into that. It's going to the Symfony Response. And there it is. So we can do response.
And there it is. So we can do response. forbidden HTTP forbidden. Okay, let's do that. Get back to here. Let's make sure to import Idea. And the next field is categoryId. And that is bound to our select inputs. So we can just do this category. Next is our statusId.
So we can just do this category. Next is our statusId. And by default, it should be the open status, which is one title and is bound to our input box. So this title. And the last one is description. And this description. Okay. So there's no success message yet. We'll add that in a second.
So there's no success message yet. We'll add that in a second. Actually, let me just add that now. So there are a few ways to do this, but I'm just going to stick with a flash message. So we can do session flash, let's say successMessage. And I'll just say Idea was added successfully. Yes. Okay. So we also want to reset the form. So Livewire provides this reset method.
So we also want to reset the form. So Livewire provides this reset method. So let's make use of that. And I also want to reload the page. So a lot of times you don't want to do that. But in this case, I do. So I'm just going to redirect back, say return redirect. We can just say idea.index. Okay. So let's see if I did everything correctly.
Okay. So let's see if I did everything correctly. Let's try to create a new Idea here on the form. So I'm logged in. Let's say Andre's new Idea, say category three. This is a description for Andre's awesome Idea. Okay. So let's see if this works. Submit. And it looks like it does work.
Sort and Show Success11:56
So it does work. So let's switch up the order first. So I want the latest first. So that would be in our IdeaController. Yeah. So here we can change the order. So I believe we can do latest or we can do something like this latestId, or we can do orderBy id and descending. Whatever you think is more readable. I'll stick with this.
Whatever you think is more readable. I'll stick with this. So now if I refresh, this will change and our new Idea should be on the first page. So let me go there. And now it's showing the new Idea first. Okay. Let's make sure to add the success message. So back to our create Idea form, let's put it underneath here. So let's make a new div. I believe I have a snippet here for the success message.
So let's make a new div. I believe I have a snippet here for the success message. Okay. So just checks if there's a session variable called successMessage and outputs it. Let's just change the classes here. So let's just make it green and give it a margin-top. So let's see if that works. Now. Let's refresh. New Idea.
Let's refresh. New idea. Awesome idea. And let's try this. Okay. So it does show there. So we'll polish this up a bit later on. But one thing I want to add here is maybe make it disappear after two or three seconds or however long you want. So let's quickly do that with Alpine.
Auto-Hide Flash Message13:36
or however long you want. So let's quickly do that with Alpine. So let's make this an Alpine component as well. And we do need some state here. So let's say x-data equals, say, isVisible, true by default. And we can make use of x-init to run some JavaScript when this component is initialized. So let's do that. Let's put it on its own line because we need a few lines here. And we can just make use of setTimeout in JavaScript. And that takes a callback.
OK. So let's see if this works. So it should disappear after five seconds. Testing Alpine. Testing Alpine transition. OK, so submit. See if it disappears after five seconds. And it does not. So what am I doing wrong here? So yeah, I have a few typos here, duration.
Add Validation and Errors15:35
So yeah, this should work on the show page as well. So if I click here, the form still appears here. So let's try this out again. Again, show page, and it should redirect back to the index page. And it does. Cool. I totally forgot about validation. So let's quickly do that. So back to our CreateIdea class. Let's add a rule set here.
So back to our CreateIdea class. Let's add a protected rules equals an array. So let's say title is required. And let's say minimum four characters. And let's add other ones for category. So this is required and should be an integer. OK. And description can be the same as title, required and four characters. OK.
And description can be the same as title, required and four characters. OK. So now let's add a semicolon. And let's make sure to validate here. So this validate. OK. So let's save that. And in our view, we can just add the error directive. So let's put it for title here underneath the input. Let's say errorTitle.
So let's put it for title here underneath the input. Let's say errorTitle. And then let's make it a <p> tag. Say text-red, text-extra-small. Oops. That should be a .. And let's give it a margin-top of 1. OK. And we can just output the errorMessage here. And we can do the same for the others as well.
And we can just output the error message here. And we can do the same for the others as well. Let's close that. And let's grab this. Let's add it for category as well. So let's put it here. And it should be category. And for the textarea, let's just put it underneath the textarea. And it should be description. So let's see if that works.
So if we hit Submit, the browser takes over. I have to refresh. There we go. OK. So now we can make a commit. I actually made a commit without doing the validation. So I had to undo it. So let's go ahead and do it again. So git add. What episode is this?
So git add. What episode is this? 15. git commit. Episode 15. Create ideas.
