Refactoring Form Validation
The editor lost focus on every keystroke due to how validation state was handled. The solution extracts error display logic into a separate ErrorField component, simplifying state updates and preventing unnecessary re-renders.
Controller Validation Adjustments
The validation logic in the controller is modified to return only error fields instead of re-rendering the entire form. This prevents the editor from being reinitialized and ensures smoother user interaction.
Fixing Update and Delete Behavior
An issue with the delete button disappearing after saving was resolved by correctly passing the article ID during updates. This restored expected CRUD functionality.
Making Table Rows Clickable
Table rows are enhanced with click handlers that update browser history and issue GET requests. This enables row-based navigation to the edit page, improving usability.
Debugging Login and Authentication
Login failures were traced to improper request handling and mismatched data binding. The solution involved adjusting form submission to use the correct request method and implementing proper flash messaging and redirects.
Handling Database Seeding and Errors
Migration resets and seeding were verified to ensure user records existed. Error logging and flash messages were improved to provide clearer authentication feedback.
Preparation for Production
With core functionality working—validation, editing, login, navigation—the focus shifts to optimization, error pages, and deployment setup for production readiness.
Okay, so we left the article form in a bit of a weird state. Our validation is working, but now our editor is unusable because every time we type we have to re-click in. Obviously, that does not work. So, see here, I'm still, yes. So, what we will do is that we will
Instead of sending back both the value and the error, we will simply extract this error value right here and create a new component called error field or error value. We're going to extract the error span into an error field component. We accept the name and an error type string. So this simply becomes the error here.
Then we add an ID and we just say name plus error. Like this. And then we go down and we place all of them. So we pass name and then we pass prop error. Then we just replace all instances of this.
And we also need to add it to the state to toggle button here for the state of the article, which I think is a fine trade-off we are doing right now. We might want to show some error messages depending on what we are trying to do here as well. So if we try to publish, but it's in value, we might show the value of the error message here instead of showing it in the bottom of the
the editor, right? So I think this is fine. We're not going to be interactivated, but we need to return it so that we can loop over all of the fields and then just return and set the error every time we do the validation check. So with that, we need to jump into our controller and take the validate article data. Now we
We don't want to send back the entire form. We're just going to grab our loop over the key value. Let's return from the two field props. So I'm just going to comment this out for now. And then we don't return. We say if error equals to SSC patch element tempo.
In here we return the error fields. Let me just finish the if, so we don't have an error. We pass in the key and then we pass in value.error. Close it off. Get rid of this. We also don't need this anymore. And we can return null because we don't need to re-initialize the editor anymore.
Right, let's now jump out here, open the console and try and see if we can type in here. And we have an error. We can find one of the fields. So what are we doing? We have to check the two article props here. It's looking at
state so that should be correct and it's looking at title alright let me just grab the validate article data here so we do let's give this a refresh and let's just check the mmm yes we have that we have
That's okay. We also have the state error, right? And for the code editor, article content error. So that is also right. Let's go in here and just lock out the keys. I'm gonna kill the development server.
and do it right here on screen. Then we type. Right, so that is correct. Was it just because we didn't properly refresh the browser? Let me try and remove all of this. And okay, so we probably needed to properly restart our developer server.
Let's now test here if I can keep typing in this field. And now I don't get any unfocused events. I can still type as much as I want. And we still have the error. And if I try to save now, we don't save because the title is not valid. But you maybe have seen that we
miss the delete button down here whenever we press save. So we need to fix that. So whenever we press save here, save now, we get that the delete button gets removed. And if I kill this, go into controllers. First of all, let's clean up this one right here. Then we have the update article where we should not pass
UID nil, but pass the incoming ID that we get from the param. Let me run the development server in the background. Go in here, trigger and validation error, and try and press save. And now we keep the delete button. Can I delete this article? I can. Great. So now our validation is working.
edit is working in the edit as well in the edit page. The only thing I want to do now is I want to make it so that we can click a row here instead of having to click the edit button so we can sort of surpass the expected table behavior or expected
how you have to do it in a proper HTML table. I think most people are used to be able to do click rows in a table. So let's fix that now. All right, so to make the table rows clickable, we can go down to the row or TR element right here. And then we specify our data on click that now needs to do two things. It needs to push the
path into the URL and it also need to issue a get request. So we get the data back that we explore the data, the temple back, the HTML back right that we expect. So let's first say window history push state. There's going to be parentheses and brackets. And in here, we're going to say empty string.
And then we want to provide the route. Yes, I need to be a little bit careful here. So we say string, sprint F, wrap this all. And in here, we want to say, what do we want to say? So we say strings, replace, say routes, edit article page.
We pass in the article ID string, and the first instance writes, that should be enough. We also need to pass in the param, or the thing that we want to replace. Great. Now, if I give, go in here.
So now if I click, we get the correct URL pushed. Great. Then we can add a semicolon and say get. And then we simply need to pass in the same routes, right? Yes. So we just repeat all of this.
Let's go back, let's refresh and now you can see we correctly go to the edit page for the article we wanna look at. And we also have all of our navigation workings. The only thing now that I'm missing is that if we go, can we log out, we actually don't need. So if we go to slash log in, we have,
We have everything working as expected. Yes. So, mpv add master full stack golang.com password. Yes, we do have an error. And that is because, that is because whenever we try to log, so let me jump out and check the,
We use the input fields. That is all good. The post here is sending us... And this is also why in the next module we're going to be dealing with lucky error pages, because this just doesn't really work to go into production with.
So let me just try and figure out why we have an error. So error here. Bind error. Okay, we need to do it like this. Let's say it's a model error. It's a validation error.
It's a flash error. It's a cookie error. It's a flash error. And then run the development server here. Go to log in again. Let's try and send it. masterfulstackolang.com pass.
Word, what do we have? No rows in data set. Right. So first of all, if I do just reset my creations and then do up migrations, then we just seed, then we run it again.
Go back here and say mpv add master full stack go lang.com password. No results. Okay. Did I change the seed command? We are not seeding with the user, right? But this also gives us an opportunity to fix a mistake that should probably have been fixed from the beginning, but here we are.
Get rid of all these log statements now. And let's actually just make our life a little bit easier here and say, here we're gonna say flashinfo. Flashinfo could not authenticate user. And then instead of
redirecting to the admin page. We redirect to the login page. Here we go. Let me grab all of this and do it for this one as well. And let's also here we do it. Login successful, login successful. Do we wanna say that here?
I actually like to just go with, let's just keep it consistent. And now let's run it, just run. Let's go back, what do we see, login unsuccessful, great. Now I just save.
reset migrations just up migrations just seed run and now mbv add master full stack go lang.com password login unsuccessful let me check this seed data
Okay, so we do create it right. Let me see, I probably misspelled it. No, okay. Interesting. And then,
lock in here. So we should have the user but let's just make sure. Let's do an error. Could not find user error error.
It's now to MVV at masterfullstackgirllang.com password. What does it say? No results in error set, which is very weird. So just reset migration, just up migrations. Go into seed, let's just make extra sure that we slug info, user created.
All right, just seed and we do have the user created. Now MVV add master full stack go lang.com password, still the same error. All right, interesting, very, very interesting. Right, there we are experiencing right now is of course that we have this data bind
attribute on the input field. So we are not receiving any data because the login page is sending a regular post request and not using data star. So what we should do instead is just to say data on submit and then we have type submit. Yes.
And then in the controller, on the login controller, we just want to say, we want to grab SSE, this one, find logging. And then down here, we don't want to redirect as normally, we want to use SSE to then say this, redirect to route.admin. Finally,
Let's try and run it one more time. This was a little bit annoying, but okay, fullstackgirllang.com passwords. Okay, and I swear I do this professionally, but I just forget. I just forget. So of course we need to say FMT Sprint.
And if empty sprints, we do, of course, a post request. Let's try again. Let's move this a little bit to the side here and say mbv at masterfullstackgolan.com. There we go. It took the long way around what we got there. We can now go in.
to that and we can also log out, right? Yes, we can also log out. Great. So we have done a lot of work here and we are so close to being able to go into production. I just want to deal with some optimization so that we can actually show up in the search result and have users find us. I want to deal with some error pages. We just have a few.
minor things that we need to do before we can actually start to push this live in a production environment. But that's not that much more to do here. We are basically done. So next module, we're going to be doing some production preparations. And then in part three, we are actually going to be setting up the server and deploying the application live and seeing it out in the wild.