Route and Controller Setup
A new route is created for /admin/articles/new using an admin prefix to reduce repetition. A corresponding controller is added to render the new article page, following the standard web flow: create route, create controller, register route.
View Creation and Layout Structure
A new article page view is defined and wrapped in a base layout. A styled container and form structure are added, using a POST method with a placeholder action endpoint to be implemented later.
Reusable Form Components
Reusable components are introduced, including an input field and a textarea. These accept properties such as name, title, value, and type to support future updates and validation.
Article State Selector Component
A dedicated component is created to handle article state using radio buttons for draft and publish. Conditional logic determines which option is selected, and styling updates dynamically based on the chosen state.
Form Completion and Submission Flow
The form is finalized with fields for title, excerpt, content, state selection, and a submit button. Submission currently routes to a placeholder endpoint, with plans to implement persistence and validation logic in the next step.
So to create the new article page, we need to follow the flow we have done a few times now. We need to first create a route and here we need a new article page route that should go to slash admin slash articles slash new. But we're also seeing some repetition here. So let's just create another variable called admin, yeah admin prefix that goes
that is just slash admin. And then we can down here remove this one to be admin prefix. Delete this and say add in prefix plus new articles form and everything is named based on this slash admin. Then we need the controller. So we're gonna jump into controllers here.
And can I grab anything? Let me just grab this. Fill it out. So we need a controller and we're gonna call it new article page. Where we are simply just gonna be returning render, we pass EC and we're gonna pass something we're gonna call new article page. That does not exist yet. But we're gonna register
the route with the controller and then we will actually create the page show new article page and new article page that we do not call write. Simul, you've seen this many times before, create a route, create a controller, register it, that is the typical web flow. Now, let's actually begin
working on the article page where we will need to create a form element, and we're gonna be creating some form components, so we can easily reuse what we have when we get to the other part, which is updating a controller. Right, let's jump into the views. And I'm just gonna put everything into the admin.temple file, since they technically belong together, we could create more files, but yeah, for simplicity, let's just keep it in admin.temple.
And here we're going to create the view. We just added it to the controller that did not exist yet. So new article page. That we are going to wrap in base layout. Say new article. And then we're going to be adding a container. It's going to be very similar to this container on our container, but the main element.
where instead of almost all of this, we are just going to be using a width of four Excel. Everything stays the same. We could technically pass this as a class or make this into like an admin page container component. Sometimes it's not really worth the effort. So we're just going to copy paste this and have the one change.
is not as big as our table, right? Next, we're gonna say new article in an H1 element. What do we want for classes? We want to say a little bit of margin on the bottom, text to Excel, font bold, text, text base content. And then we want our form.
And if you have never done traditional forms before, we simply wrap things in a form element, provide the method and the action and the action is gonna be the endpoint that the, or yeah, let's call it endpoint where we're gonna send the form data to. We're gonna write it with some fields of different types that is gonna have a name and a value and then
you can visually think of this as like a JSON where the name is the key and then the value is the value. Right. We need to say, specify the method, which is going to be a post request. Then we also need an action that we're going to say to do because we have not created the controller to handle this request yet. So we were going to fix this.
in the next episode, and I misspelled form is like this. Finally for class, we are gonna say, this is a grid, and we're gonna say we have two columns, gap of six, padding of four, bg, bg base, 300, and then we're gonna make it rounded. And,
We should actually be able to go back and refresh our browser here and click add new article. We cannot write because we need to go up to new article that we made in the previous episode. Why is this? This is here. Add article. And instead we need to pass the routes new article page.
And if we jump back into the browser, give it a refresh, we can now go to slash admin, slash article, slash new, and we see we have the new article with a form that has nothing in it. Right, next we need to deal with the components we're gonna use because we are gonna be reusing them, so we're gonna create an input field component and a text field component.
Let's begin by creating the input field component. So we're gonna create a component like we've done all the other times. That's called input field. It's gonna accept a name, a title, a value. Then we also need a field type, and all of this is gonna be strings. Right, name is what we're gonna be using to identify the fields when we actually send the data to the controller. So in our JSON analogy, this is gonna be the key.
Then we want to have this value field so that when we get to updating, we can send the values that we actually have in the database so the user can see, or we ourselves can see when we input it earlier, and then we can make changes to that. It's also valuable to have this field when we start to add error handling, but that is gonna be in an upcoming module, right?
And as you mentioned, field type, input fields can have different types. They can be string numbers, email, telephone numbers, passwords. They have a lot of different options. You can check all of this in the MDN docs. But we are just gonna be using text for now and then we'll be using some other field types later when we get to creating like a design inflow and all of those kind of things. Right, now talking, let's do the,
wrapper here, that's gonna be a diff grid, gap two, auto rows, min, where we then gonna be a label. Oh, there we go. Yes, so we just get the rows to be the min content. All right, that's what we want.
And in here, we want to pass the title. All right, and then we want to have the input field itself. So for the label, we're going to specify a full attribute. We're going to pass it the name. And class of font symbol text.
base contents. And then in the input field, we're going to specify an ID that is going to be name. And we specify this ID and four attributes so that the browser can better provide accessibility to the fields and also it makes tapping easier so they know which fields belong together. Then we need to pass the name, which is just going to be name. We want the type of the field to be whatever we pass as fields.
field type. Value is going to be value. And then give it a save and break it up a little bit. Then we're going to pass in class to be BG base 200 border around it. And some padding on both axis. Oh, let's do
three on the y-axis and then text base content. Great. Next, we need to do the text area and then we'll implement these into our form. So for the text area, we're going to be doing pretty much the same thing. And the reason why we want a text area is that input feels really good for shorter text input, whereas text area can better be
adapted to handle larger inputs. So for example, our excerpt that might require more lines, it's really great with a text field compared to an input field so that it's easier to style it and more visually on the page what you're writing. So for the text area, we are going to be passing name, title, and value as before, but no field type. We are still going to be having the grids.
cap 2 for the container div yes and also for label and then we simply change this to be text area remove the type and then inside of text area we will pass the value give that a save can we break it up a little bit yes we can
and we don't actually want to apply any more styling. So let's get these two elements into the page and we can see what we have so far. So we will pass the input field first here and we are gonna say the names should be article title. The labels should be just title, title. We don't want any, or we don't have any value right now and it's gonna be a text
No, I accidentally hit the escape or queue when I saved. All right, we're back. Then we need the text area. That is gonna be article excerpts and excerpts, right? I mean, don't pass any field type.
Yes, let's go back into our form and see what we have. And now we can see we have title and excerpt. We can write in them. And you see we have multiple lines here. We can't really do that here, right? Then we will actually submit the request. As you see, we go to the action we specified, so it just depends onto the current URL. So you can see the excerpt here, much easier to do, a longer text.
I want them to take up all the available space. So we're gonna say class call span to close it, close the diff. And then again, that looks right. Give it a safe and we now have them each on their own line. This looks a bit prettier. We need one more component. We need to be able to specify the state of the article. So we can either have draft state or publish state.
And we're gonna create a component to handle all of this for us. And there's also one of the reasons why we have the two columns. So we can have these two checkboxes to specify whether something should be released or something should be in draft mode. All right, so to add this state selector component, we're gonna say temple article state. And we're gonna pass a boolean, so published bool. Then we will say diff, close it.
quickly, say class, and then say grid, gap, oh, we're going to say grid, gap, two, call span, two. Great. Next up, we're going to need a field set. We're again going to be using grid and grid again, calls, two, we could actually let's remove the wrapper here because this is what we have.
like what we have down here, right? So we're just going to say field set, quit calls to, we're going to put in a gap and we're going to say text base content, close the field set. Okay. Yeah. So we just have form controls, right? Which is exactly what we want with the checkbox or it's technically a radio we're going to be using, right?
The fields are done, so now we need a legend. Legend. That's gonna be font bold and some margin on the bottom, and the legend will simply say state. Next, we are actually gonna be needing another two input fields. That's just gonna have a different type. So let me just grab what we have here, and we can actually adjust it.
adjusted. Where did we go with that? So we don't need to pass anything. We are just going to say the four is going to be draft, if I can spell. What do we need? Do we want to have BG base, 200, border, rounded, some padding, and then grids, grids.
We want to have grid calls five and we also want to have a little gap and center the items. Gap of four and item center and then text base content. Instead of passing a title, we're just gonna be saying, what do we actually want to save?
input field inside, and then we want a diff that says drafts. Slowly getting there. The ID for input field is also going to be draft. The name is going to be state. The type is going to be radio. And the value is simply just going to be drafts. So give that a save.
And we need to add a little bit of styling to the title, technically, column here, right? So we can say text, algae, font, semi-bold. And now we're going to be using an F statement to specify whether or not this checkbox or radio box should be checked. And if published is false, then we simply say checked.
All right. Do we actually, we don't want this. We just want to say with a four and hide a four. Okay. Grab all of this and then we simply just going to repeat it for published. So publish and if publish is true and publish, publish. All right.
And then again, publish, published, or publish, I think publish is better word here. Finally again, publish. So let's jump in and see how this looks. Oh, we are not seeing any update. That's because I did not add it. So again, we're gonna wrap the container here and we're gonna say article, article state and pass.
false, and now do we see it? We do. So we have this draft and publish, and we can toggle between them. And if you toggle the other one, the other one, the toggle, publish, draft gets untoggle by then. That's why we're using our radio instead of just a checkbox. Good. But it would also be nice if we can indicate the, visually indicate what is selected. So what we can do
which on Tailwind classes is they have this has checked class. So we can say has checked and then we say BG to be warning. So it matches a little bit more what we had in the admin page where draft was the warning and then publish was the success. So we add two of these has checked, text, warning, content and background. So we can grab these two one more time.
And then we simply just add them down here where we want to use success instead of warning in both places. Success. There we go. Jump back in. Now we have also a state that's visual from our color, the color changes, right? Great. So.
Final thing, we need to have a button, so we can actually submit this form, so we're gonna say button, close it, and we want to have, let me just call it save, and say class, we're gonna call span2, we're gonna add some padding on the x-axis, and some padding on the y-axis, we're gonna say border, rounded, bg-success, and place self,
ends. How does that look? That looks okay for now. We can probably also add, let's say hover bg success 70. So we have some visual indication as well. Right, this is our form. This is not our form. Sorry, we need
We also need to be able to put in content. I mean, you're gonna use a text area here, say content and content. Right, that's important. Now we can actually write our markdown down here. Say hello world. You can publish, we can put it in draft. We can say, I don't know, my first article. The first article error.
written on this block whatever you want but clicking save now goes to to do because we're going to add actually let's just see here you can see clicking now submits the the form but there's no endpoint to handle this we actually want to add type submit here just for a good measure so go back again
So you can see we go to this to do, that is not found. So in the next episode, we will also be adding, we were adding that controller to create the article and start in the database, but we also be dealing with validation. So we always make sure we have valid data when we create an article and draft, but especially if we select publish, we wanna add some additional measures to make sure we have our proper title, excerpt, that our content is of a certain size.