Managing Content

Adding error pages

Summary

In this video, I finish up Module 4 by adding the final components needed before deployment: an about page, error pages, and a footer. I demonstrate using Timble's method components to create the about page, then implement error handling using the functional options pattern to create customizable error pages with default values that can be overridden. I add error handling to the homepage, article pages, and create a catch-all route for invalid URLs. Finally, I create a footer component with social links and a dynamic copyright year using Go's standard library. The blog is now ready for users.

Transcript

This is the last episode of Module 4 and we don't really need to do too much at this point other than we need to add an about page, we need to add an error page or error pages and we need to add a footer. So nothing new is really going to be happening in this episode. I just want to get the last components in so you can actually take what we have and deploy it, but also show you different options or different ways that you can work with Timble and take advantage of the fact that this is all just Golang in the end. So with that in mind, let's finish up this module and get the block in a state where you could technically release it to the world. Timble has this concept of method components and method components are very similar to regular methods on a Go struct. The only real difference is that you change the func keyword for Timble. So I want to use this type of component to create our about page. So go into the views folder and create a new file called about.timble and we are still in package views. Then we create a new struct called about page that has a field called paragraphs. That's a string slice. And then we simply just say Timble ap about page and let's call this one compile. It doesn't really matter what you call it. I just call it something that is descriptive of what it does and compile is sort of what we are doing here. And then I'm just going to grab some code because we're not really doing anything new in terms of working with Timble. We are just wrapping this in the base layout, adding some HTML element, add some styling and then we literally just loop over all of the paragraphs that was passed to the struct when we created it. So far, so good. Now we also need to create a controller. So go into controller.go and create an about controller that takes in a echo context and returns an error. We're just going to say return views about page and it's called compile and then called render. And let's just grab this here. So we pass the context and the response, give that a safe and for the paragraphs, I just want to pass some lorem ipsum text. Come on, come on, there we go. So we have something that looks sort of how our real about page will look like. So there we go. Now we just need to add another route. This one is going to look very similar to how the rest of our routes look. So nothing really new here as well. And then we can go into our browser, give it a refresh and go to our page. And there we go. Now we have an about page created as a method component. So right now we are not really handling errors that well. We would literally just show a blank screen if something went wrong right now. And that is obviously not a really nice user experience. We should show them some sort of message that tells them that something went wrong and then they can click here to get back to a functioning state. And for that, I want to create sort of a generic error page component. And to do that, we're going to be using a pattern called the functional options pattern. And this allows us to set a bunch of default values for a given thing that we can then override as we need to. So this is this is really powerful to build out these generic components that have the same overall structure but might change depending on what happened. So let's go into views and create a new file called error.temple package views. And then we're going to create a new struct called error page data that is not exported. This one is going to have four fields, it's going to have link, string, going to have link title is going to be string, it's going to have title that's also going to be string and finally message that is going to be a string. Then we're going to create a new type called error page option. That is a func that points to error page data. There we go. Then we're going to create our first option or overriding function that is simply just going to be changing the title of the error page data if we wanted to. So let's just create a func here, call it with error page title. It's passed a title as a string and then it returns an error page option. Error page option, there we go. So we return a func that says error page data, where we go in and say epd title is equal to title. Awesome. Then we will create the actual error page component, which is just a regular template component as you have seen it many times before. We just wrap it in our base layout and we then use the data that we just specified up in our error page struct. So nothing really interesting is going on here. Now, before we can use this, we need to create another function that will be exported as called error page. So this is the one you would actually call in your controllers to show the error page. And this one will take in a slice of options or ops here for short. Error page option, and it will return a temple component. And then I'm just going to grab some, the default data here. So this is the data that if we don't pass any of our overriding function, this is what the four fields will take as values and to override them based on what we pass. Now we just loop over these error page options that we that we specified as an argument. So it's just a range, ops, PTS, there we go, PTS and opt data. So this will just loop over all options and then change the data based on what it gets passed. And then we simply just return our on unexported error page component, and we just pass it data. There we go. Give that a save. And now we can actually start using our error page in our controllers. Before we go ahead and start using our error page component in our controllers, I just quickly want to add the rest of the overriding functions where here we are just where here we are just changing or providing the option to change the rest of the fields with the error. Sorry, with the option optional pattern here is very important that you only change one field with one function. If you start to add multiple functions that change the same field, things can get very, very dicey. So that is kind of like the rule of thumb here with the options pattern, but now we can change all the fields or we can just use the default as we want. So let's go ahead and jump into our controllers. And let's start by updating our error here for our homepage controller where we just want to pass the default. So let's say views, error page. And since this function returns us our template component, we can just call render like all the other components. So just need to grab all of the request context and the response, give that a save. And now if something were to go wrong, we will see the default error page. And to trigger this, we can just comment that out and say if error is nil, then show us the error page. So now in our homepage, we can give it a refresh and we see all the default values, something went wrong, blah, blah, blah, go back to the homepage. So this is working as expected. Let's just change all of this back. But we of course also need to do this for our article and for our about page. And for our article page, when we are trying to get out an article based on the slog, technically the user could paste in a value that doesn't exist, you know, like they might necessarily not use the click the link that we have provided. So here we actually want to override the defaults and say, views with error page title. And let's say that doesn't seem right. And let's also update the message views with error page message and say sorry, I couldn't find that article. Let's save. And now again, if we go into our browser here, give our homepage a refresh, we are back to what we expect. Let's click the first article and change the URL up here to something like article three. And we see that this doesn't seem right. I couldn't find this article, go back to homepage. So this is also working as expected. And final thing for article is we just need to, if we can get all of the articles, something went wrong on our behalf that we couldn't really fix, right? So we're just going to return the default error page. And the same thing down here in about, we actually don't have any errors. That's right. So this is the only, this is the only places for now where we need to update the error handling. Final thing I want to do with regards to errors is that I also want to provide like a catch all route that if the user goes to something that we have not directed them to or just put in a random URL, they're still seeing a page that tells them that something went wrong, please go back to our homepage. And to do that, we can just go into our routes here and we need to make sure this is the last route that gets specified. So we do it here at the bottom, we say get star, not, there we go, star, func, sp44. And then in here we can say return views, error, page, render. And then let's just grab the, like so, the context and the response. And let's also overwrite the values here. So let's overwrite the page title, with error page title. Let's say oops. And let's also update the text or the message with error page message to say we could not find the page you are looking for. Give that a save, go back to our browsers, refresh. And if you were to go to something like, I don't know, let's say videos, we don't have a videos page, we can't find that page, go back to homepage. So this is basically all of the error handling that we need right now. So our blog is pretty much done right now. I just want to do one more thing before we go on to the next module, and that is to add a footer so we have a nice footer on all of our pages. And to add a footer to all of our pages, we just need to create another component here. So I'm just going to again, copy paste some code. That simply just creates a footer. And then we have some socials here. We have Twitter, LinkedIn, YouTube, and then the name of the blog and all rights reserved. And we just had at the time of recording, at least this was just after New Year's. And since this is all Go in the end, we can use Go's standard library to actually calculate the current year so we never have to go in and update the year for the copyright symbol. Now final thing is that we are going to be passing or adding footer here and go into our browser, give it a refresh. And now you can see we have this footer down here, my blog, all rights reserved and some some socials. And this will also show up down here. And on our about page. So our blog is now actually ready to to be sent out to users.

Early Access

$95 $65 USD

Get access

Invoices and receipts available for easy company reimbursement