Routing and Edit Page Setup
The edit functionality is introduced by defining a new route that includes an article ID parameter. A corresponding controller method is created to handle requests and render the edit page.
Fetching and Passing Article Data
The controller extracts the ID from the URL, validates it as a UUID, and retrieves the article from the model layer. The article data is passed to the view through field props to prefill the form.
Form Handling and HTTP Constraints
Since standard HTML forms only support GET and POST, a POST request is used to simulate an update operation that would typically use PUT. The form is updated to send the article ID and existing values for editing.
State Management (Draft vs. Published)
The edit view is enhanced to correctly reflect the article’s publication state. Logic is added in the controller to map database values to either draft or published and pass the correct state to the template.
Update Route and Controller Logic
A new update route and controller method are implemented to handle form submissions. The controller retrieves the payload, validates inputs, and calls the model layer to perform the update.
SQL Update Query and Model Changes
An SQL update query is defined to modify article fields such as title, excerpt, content, slug, and publication timestamp. The model ensures only changed fields are overwritten and preserves existing values when appropriate.
Conditional Field Updates and Validation
The update logic compares incoming data with existing values to selectively update fields. Special handling is added for the publish state to correctly toggle between draft and published.
Debugging and Testing the Update Flow
Logging is used to inspect payloads and parameters when issues arise. After correcting logic errors, updates persist correctly in the database and reflect in the UI.
End-to-End Article Update Workflow
The system now supports editing, publishing, unpublishing, and persisting article changes. The next step mentioned is adding toast notifications to provide visual feedback after updates.
All right, let's deal with updating an article. And again, we're gonna start in routes, and we're gonna say, no, not this one, we're gonna say this one, and we're gonna say edit article page, and we will say edit. Then we need to create a controller. So we are doing exactly what we've been doing a few times now.
Edit. Oh. Come on. Edit. And edit. Great. Actually, I need to change because we're going to say articles, pass an ID, and then edit. So we have the article we want to target. All right. And then we can go back into the controller.
And now we need to pull out the ID from the param. And do we do this earlier? No, but we can grab this one and then modify it. So we say ID and ID. Well, let's say ID param because we need to pass this into an ID. So you can say ID error, you can say UUID, pass, pass in the ID param.
Ram, return an error if there are any, and then we're gonna grab the model. So we're gonna say, article, error, models, fine, article, pass the context, pass the connection, and then pass the ID. Yes, again, we're just gonna return the error, and we still need this edit article page.
Right. So what we want to do is we want to take this, we want to click edit an article, we grab the database and then we pass the data to the view through the field props. And then we can start to work with what we have in the database. So before we hook this up with the field props, let's go into the admin dot temple file and we update
basically gonna be repeating all of this. So we're gonna say edit, and then we're gonna, here, gonna say edit as well. So we could technically wrap all of this in a component and then only update what we need to update.
or change button to change because these two are very similar, but we also want to change the base layout. Do we want to add the title fields? You could. But then again, this is fine. The only real thing to note here is that maybe if you have done any APIs before, you will probably think we are updating something. We need what is known as a put request. That we cannot do.
with the current state of standard HTML forms. We can only do a get and a post. So we are forced to do a post request for what should technically be a put request. When we get to modern hypermedia or the module about modern hypermedia, we are going to be updating this so we can use the correct HTTP methods. But for now, this is perfectly fine. Everything is good. So let's go.
You're jumping a little bit around here, but you've seen a lot of this before, so it should be fine. You're gonna say, here we're gonna say edit instead, update both of them. We go back to our controller. Then we're gonna say, let's say props equals two. Past the props. And then in here, we are going to be grabbing
Let's grab all of these and say article title. And no, of course, we need to say field prop like this. There we go. So value, article, title, grab,
this and add it here and say excerpt. Finally, add content, restart the LSB. We have no errors anymore. Right, but we also need to be able to tell the components here about
the ID that we are working on. So what are we going to do? Well, we have this edit page here that takes in an ID. So we also need to pass the article ID. It's going to be UUID, UUID. Then we're going to say, again, string replace on the edit page.
I'm gonna say ID, ID, come on, ID, article ID.string. And the first instance, go back to controller, give it a refresh so we see the error. Where did I make a mistake? I made a mistake here.
Now go back to the controller. Restart it. Do we get an error? We do not. Okay. So we have some errors in our... Yes. You of course need to be able to spell. Replace. Strings replace and then add the URI-D to the import.
Let's see if this works now. Okay. So I can see in my development server that's running in the background that it is actually working. So let's just try and pass in the ID. Let's jump out. Let's jump back into the controller here. Do we have an error? We do not have an error. Great.
So we create a route, we register the route with a controller. In the controller, we grab the ID from the URL, we pass it into an UUID, we grab the article from our model layer, we set up the field props, we pass that along with an ID, and we are technically doing a little bit of repetition in the UL layer, but that's fine because, yeah, I mean, you could do
Some very complex stuff, but this is also easier to read. And we might have a situation where we wanna do different kind of things. So don't worry too much about that for now. But to be able to see the edit, we need to remove this to do here. And again, we need to say strings. Actually, we have it already. Whereas it is right here. So let me just copy everything in that one.
There we go. Pass this. And article.id. Give that a save. We jump back into the browser, and now we should see in the bottom left, we can click an article. Let me close this. And we see that it's filled out with the test article title. If we go back, let's take one that's published. You can see we have the values, but we also need to fix this state.
Let's do that first. Let's update the state here to actually take in the field props so we can have the correct statement when we go to edit an article. So back in admin.temple here, and you can see we passed this false here. So we could either pass the release date from the edit page as an argument, and then it will work on the edit page, but we also have it on the new article page where we handle errors.
So what I want to do is we're going to add a field prop. And it's essentially going to be, if you say props, and then we're going to say article. No, let's just say state. State. And then I'm going to say value. And if you say published, then it evolves to evaluate the true. Do that in both places. If we go back.
Does something change? It's the same. All right. Jump into the controller. And then in the new article page, we don't do anything, but in this one, what are we going to do? We are passing in here. Okay. We have the payload so we can just say state.
is equal to state and again, I am missing, so state and state, right? We are free balling a little bit here. All right, so this will be equal to either publish or draft. So we return that,
Let's go back into the view and not say publish, but let's just say publish. I think that works fine so that it works in here because that's the state that it will get. Yes. Now in the edit page controller here, we also need to say state views.
yield prop value and then we have article and publish that is zero. And what do we want to do here? We want to let's just create a state saying let's say bar state string if
If this is zero, I can do this so much smoother, so it's draft. And then if it's not zero, we say state publish. Okay. Now. Okay. Yes.
We are getting the promise. There we go. Now it's working as expected. Great. Let's add the controller to accept the update values and then update.
article, and then we also have a lift over from the previous episode. I need to show you what actually gets sent from the browser to the controller. Right. We're going to do this one more time. Router, routes, routes. And we're going to grab, no, let's grab this and we're going to say update article. And again, it's going to ID, but we're going to pass it update instead. Then in the router,
We're gonna do this again. Say, update article. It is also gonna be also going to be update article. Jump into the controllers and let's take our create article here. And underneath it, we're gonna say update article. We are doing
Almost the same thing here, we need to grab the payload again, and we also need to grab the ID parameter and pass it. So in here, have the ID, and let's just do this for now. Declare not used, yes, update, update article.
and we do not have an update article model. That's right. All right, so let's add an update article model, and then we can finish our controller implementation. And before we can create our model, we need to add a new query. So I'm in the articles.sql file here. We're gonna create
update article and what we do we do update table articles set and now we need to not do created that but we need to say updated that that would be equal to now then you'll have title be equal to argument 2 because first one is going to be reserved for the id
And then we want to say excerpt equal to argument 3, content equal to argument 4, published at equal to argument 5. Finally, slug equal to argument 6. Update table articles, set these ones.
where id equals to argument one. Great. Let's jump out and see it just generate queries. Let's wait for the tool to do its thing. I have an error. I can't remember how to do updates anymore.
Update, update, update articles. It's update articles. It looks like it. Let's just see what it created for us in the internal layer here. So articles, do we have an update? Update, article, date, articles, set. Great. Then let's grab what we have here from create article.
It's going to be update, article, and we're going to accept an ID of UUID. We are still going to validate, but we're going to use an update, article instead. And the parameter also be update. But we need to make sure that we don't, we only overwrite the content we need to. So we're going to say params.
and then we're gonna pass in the params here. Give that a save. Then we're gonna say, let's say current article and say db. Actually, we can just say find article, pass in the context that db, tx, and id. Return the error if the
are any. And then we have the article, yes. So the params is gonna be current article ID. This is gonna be current article.title. This is also gonna be current article.title. Like so, like so, and so.
valid so it's going to be not published it's going to be published at is zero one more time for the content all right so we simply set the parameters to the old value and then we can go in through our the data we have so we say data dot
title does not equal an empty string, then we will say param, params in plural of course, params, title equals to data.title and also need to update the slug with the new value. So let me just make this work, grab this,
Grab this, do this, and slug, yes, data. And here we know it's true. Repeat this for the excerpt. Excerpt is just this, so we can say params.
xserved equals to data.xserved. For content, I'm going to say again, if it's not equal to an empty string, then we actually update it. Content. And this can be a null field. So we need to use this pgtext again and say data.content. And this is true.
All right, now we need to compare. Do we need to compare? So if we say, if data publish. So if data is said to publish, all right, and data.publish, no.
burned article published at. So we set something to publish. It's true. And this one is zero. Then we update it. Is that not right? I think I'm right.
Times dot publish that equals. Yeah. Yes, I like it. And if you probably just do an else here. So we have to always pass if it's something set to publish or not. And if it's not set to publish,
Then we simply say, it's true. And then we can leave this one out and set this to false so we can unpublish an article. We update the article and then we return the value. So a few things happen. We still validate. We find the old article. We set up the param struct.
that the SQLC generator for us, then we check the value of what already exists, or what is passed versus what already exists, and then we update the programs accordingly, we pass the program, we update it, and then we return the model. And then we simply jump back into our controller, and then we have the update here, and we have the update article, let's say article,
And that is good. We just need to pass the ID. And we still check for validation error. So we'll be using quite a bit here. And we're going to render the edit page. That also needs to have the article. No, they just passed the ID here.
If nothing else goes wrong, we simply do exactly what we do in the original case here. And state also needs state where a state is here.
Right. Let's try and actually update an article now. If you give this a refresh, let's try by altering this state. This one says new article. Why didn't I fix that before? Edit article. All right, here. Edit article. Edit article, sorry.
Let's try and set this to draft. Method not allowed. Okay, we post to the edit page. That is because we don't post to the update article page. Okay, let's try one more time. Can we actually update now? We
but nothing happens. Okay. Let's go into our controller here. And we have params as before. We get the ID. Let's start by logging out the payload. Let's just say payload, payload, and finally payload.
state, let me kill the development server and bring it up here, just run, go in here, draft, save, and we do get draft. Okay, so maybe I have something in my logic that is wrong.
So we set the... All right, this is set to publish. This should be... The true and should be... This should also be set to zero. So let's jump in here.
and let's try and log out the params instead. Model article, model update params, params, params, and finally, params. So one more time, just run, give it a ref.
Let's go is one more article right to go into one more article draft safe. And what do we have published that is set to a valid timestamp. Yes. So my logic is wrong. And that happens more often than I'd like. So.
data.publish is equal to this, but that should definitely not be the case. Right, data.publish should be false. I think we need to do, probably gonna be doing this.
Again, go to admin, one more article draft, save, and now it stays as a draft because so see one more article is draft. Great. Can we update the values here? So see one more article updated. This has been updated. Save it. We get back here. Go to admin just to
be totally sure, no, which one, this one, one more article updated, right? And the values are persisted. Let me just quickly show what is actually sent here from the front end. So if we turn this back into publish, you can see we have a request here, where we have a payload, and this is the form data that we can see as source or past and decoded. And these
Values here are the names that we add to our field or our field components, and the values. And this is then what eco passes for us in the controller. Right. That was a long way to get to here. But now we can update articles. We can publish them. We can modify the content. If we go to home here, we can see the latest one is the one more article updated. Let's go to one more.
article updated and updated again and make it draft, save, go to admin, one more article updated again, and it does not show up here anymore. So that is how you do create and update. But I would still like some visual feedback when we initiate an action here. And for that, we're going to be using toast messages so we can showcase a little
little box up here in the top right corner with a little message saying article was updated or and ever happened or whatever we need.