2.7 Layouts and Rendering
You may want to differentiate the distinct parts of your applications with special components or content layouts. In this lesson you’ll learn about using custom layouts and rendering options to accomplish this.
1.Introduction2 lessons, 14:01
2.Building a Rails Application11 lessons, 2:09:35
3.Conclusion1 lesson, 02:23
2.7 Layouts and Rendering
In this lesson I want to show you a little tip on layouts and rendering some content. Let's say, for example that we want to switch the layout for the projects list. I mean, we are using the layout on the entire application but let's say, for example, that this projects list demands a different kind of layout. So let's solve that challenge right away. As you can see, we have the previous layout. It is the only one we have. For the sake of the example I'm going to copy it, but instead of using an application name, I'll use, for example, projects.html.erb. Let's say that in this particular example, I wanna have some sort of a navigation bar on the right side. And because of that, I need to change the way this layout works. So, in this container div, instead of using this one, I'm gonna use, for example, container projects, and I'm going to create yet another div. It is going to be called sidebar. This sidebar div will have some information on the side. I can immediately choose to create a header here, called sidebar. And this will assume that there is a sidebar right next to the container with all of the content. Of course this is not the case, because when we do so, well, we still don't have anywhere to declare the layout to be rendered. So regardless of hitting reload multiple times, the layout won't be used. So, in order to use this projects layout, we're gonna have to go to the controller. Let's go to the project controller, and use the layout option. The layout method is available in each different controller. That basically allows us to define a layout to be used in each and every action. With just this instruction and no other arguments, all of the actions in this project's controller will use this layout. Actually instead of a symbol, it should be a string. If we use a symbol, then it's going to look up for a method, so it wouldn't fetch the appropriate template, but rather call a method. Stick to a string and it will directly fetch that projects HTML ERB layout. So if we save now and reload the page, you can see that the differences are really telling. First of all, we don't have that container div, and the side bar is not on the side. Basically, we need to change some CSS in order to accommodate these changes. Let's go to app.css, and I'm going to include two new IDs. So, container projects and also the sidebar. So we'll add in that rule as well. And from here we'll be able to establish direct measuring for each div. The width of the sidebar should be something like, I don't know, maybe 33% or 25% and the container for the projects should have something in the terms of 75%. There you go, so basically three-quarters will be for the main area and 25%, just a quarter, for the sidebar. There's one thing that I'm recalling now. In the projects layout, I still want that container div because I want to center the content and the sidebar inside them. So just indent this and make in place. And when saving and going back to our browser, we will see a major difference. Now we have the same margin on the sides, but notice how this is still under the main content. There's something that I forgot to do, and that is by going to the app.css file, both of these should be floated to the left side. So let's go ahead and take care of that really quick, and when we do this, both divs will be in their respective place. So if I hit reload now, there you go. Now we have the main content on one side, for filling three quarters of the screen, and then the sidebar with just a quarter of it. So that's pretty good. Notice how I entered the Show page for one project, and it still works. However, if I go to the Task, you will see that this is no longer the case, because it's not using that layout. So what if you want a different layout for a specific action? Let's say, for example, that you want to keep the application layout in the show method. You use render and then the layout option and pass application. Basically, for this specific scenario and this controller, this action will have the normal application layout. So when you do this, reload the page and switch to the Show page for one project. There you go. The normal layout will be applied. Now, let's do one other thing. I wanted to show you the power of using the yield command. As you know, in the layouts, you have this yield command. But I had a reason for creating this project's layout with a sidebar. Indeed, I wanted to create some sort of a placeholder for content in the side bar. What I want to do here is yield a content that has the proper semantic. So if I type in yield and then a parameter, so if I type in something like yield(sidebar), all of the content that's registered for this placeholder will be yielded and rendered in this place. So basically, everything that's registered in this placeholder will be here. Now, as far as the content exactly, if we go, for example, to the list of projects, I can go here to the very bottom of the file and actually type in the following instruction, content_for, and then sidebar. We need to pass a block so that the content that's inside will be rendered in that placeholder. This might sound a little confusing to you. Maybe you think that this content will be printed out right after the previous main content, but it won't. You're basically executing some code inside this template. However, this is the best place to do so. For this specific page, I want to introduce, for example, a list of projects. So let's type in something like a header with All projects. And I just want a list, an unordered list, with each list item to have, for example, the project's name, so, project.name. Don't forget that we need to loop through all of the projects, so we need to type in Project.all.each, and pass in the project, and close the block, like so. This was probably a little too fast, so let me explain you what this is doing. Remember, content_for allows us to register some content under this placeholder, which will in turn be rendered in the correct place in the layout. Next, we have a title, which is pretty straightforward, and a list that will loop through all of the projects, and you type in Project.all and you loop through each of them. Project.all will retrieve an array of different project objects. For each one of them, I want a list item with the name. And that's it. If I reload the page here, let's just go back to the list of projects, and there you go. All of the projects are here. Notice how easy it is to fulfill this kind of scenario. I can't count the number of times that I tried to do this in other systems. But with Ruby, it is really this simple. So these are the basics of using layouts and content placeholders.