When you install Orchard 1.9, the first thing you might notice is that the Page
content type no longer contains a BodyPart
by default. Instead, it now has a LayoutPart
.
Make no mistake, the BodyPart
is still absolutely relevant, that will not change. Experienced Orchard users typically design their own content types, and the BodyPart
is a very useful part to represent a type with a body of text.
To new users, we want to show off what you can do with Layouts. Take for example the "Home" page that is created when you setup a new site using the Default recipe:
Notice any differences? No? Let's have a look at the page editor:
What you see above is the layout editor used to layout the homepage. By default, the Page doesn't have a BodyPart
anymore, but a LayoutPart
which is responsible for rendering a layout editor.
A layout is a hierarchical collection of elements, such as Grids, Rows, Columns, Html, Markdown, Paragraph, Image, and more.
And Orchard wouldn't be Orchard if you wouldn't be able to extend thhe list of elements with your own elements.
The following is a high-level overview of all that Layouts currently has to offer.
When we first introduced the layouts feature, one of the first questions asked was: "How does layouts relate to zones?"
The short answer is: layouts have nothing to do with zones.
To clarify further: columns in a layout are not widget zones, and are not intended to "design" your theme. Instead, you use a layout to place elements (optionally using Grid elements) into the local Content zone of a content item.
In the first screenshot of this post showing the new homepage, what you see is not the three standard widgets (they have been removed), but simply the Content zone that renders the LayoutPart
shape (Parts_Layout
).
Since the LayoutPart
is attached to a content type, the shape created by its driver (Parts_Layout
) will be added to the Content shape via Placement.info, just like any other part shape such as Parts_Title
and Parts_Common_Metadata
, and the Content
shape itself is added to the Content
global zone.
Our of the box, Orchard uses a small CSS file called "default-grid.css", based on custom-grid.css from Sébastien Ros. It's a lightweight CSS file to implement grids without relying on full-blown CSS grid frameworks such as Bootstrap.
However, if your theme is using Bootstrap, you most certainly will want to have the LayoutPart
render the grid, rows and columns using Bootstrap specific classes.
To do so, follow these simple steps:
This is how these files look like after the changes:
Views/Elements/Grid.cshtml
@using Orchard.DisplayManagement.Shapes @using Orchard.Layouts.Helpers @{ var tagBuilder = TagBuilderExtensions.AddCommonElementAttributes(new OrchardTagBuilder("div"), Model); tagBuilder.AddCssClass("container"); } @tagBuilder.StartElement @DisplayChildren(Model) @tagBuilder.EndElement
Views/Elements/Column.cshtml
@using Orchard.DisplayManagement.Shapes @using Orchard.Layouts.Helpers @{ var element = (Column) Model.Element;
var columnSpan = element.Width; var columnOffset = element.Offset; var columnOffsetCss = columnOffset > 0 ? "col-sm-offset-" + columnOffset : default(string); var tagBuilder = TagBuilderExtensions.AddCommonElementAttributes(new OrchardTagBuilder("div"), Model); tagBuilder.AddCssClass(String.Concat("col-sm-", columnSpan)); tagBuilder.AddCssClass(columnOffsetCss); } @tagBuilder.StartElement @DisplayChildren(Model) @tagBuilder.EndElement
Views/Parts.Layout.cshtml
@Display(Model.LayoutRoot)
Instead of overriding the shape templates, you could consider to just "retarget" the "span", "offset" and "table" classes using Bootstrap mixins. Either way is fine and completely up to you.
The following is a list of elements that come with the box.
Being able to create layouts is fun and creative, but there are times where you need the same layout over and over again and you wish you could somehow reuse some sort of layout template. Well, we have that too.
When you enable the Layouts feature, not only is the LayoutPart attached to the Page content type, but a new content type called Layout is created, whose definition looks like this:
What sets apart a Layout content type from a Page content type is that it:
The latter is what makes a layout reusable.
Now, let's imagine we have a website where we have many pages with the following layout structure:
The layout could look like this:
Next, imagine we created three pages, appropriately named: Page 1, Page 2 and Page 3.
For each page, we'll add an Html element with a text of something like "Layouts Demo" to the first row, and we'll add some copyright notice to the first column of the last row.
Page 1 could look something like this:
Notice that for Page 1, we selected the "Master Layout" as its template and added two HTML elements.
We could do the same for "Page 2" and "Page 3".
Page 1, 2 and 3 are using the "Master Layout" as their template. Whenever we make a change to this template, that change is reflected across all pages using it.
For example, let's edit "Master Layout" and turn its first row into a yellow color and add some logo to the lower right column:
Hit "Publish Now" to publish the changes and check out what "Page 1" looks like:
As you can see, the pages using the layout template reflect the changes we just made to that layout template.
You could even implement an hierarchy of layout templates where you have a common ancestral layout defining just the layout structure for example, and reusable child layouts defining some content in the form of elements.
Content items could use any of these reusable layouts, and a change anywhere in the hierarchical chain will cause all descendants to be updated.
Another feature that comes with layouts is Element Blueprints.
An Element Blueprint is more or less a preconfigured element based on an existing element.
For example, we could define an element called "CompanyInfo" based on the Html element, containing information about our company.
We can now reuse this element in all of our pages. We could even create a widget called "CompanyInfo", attach the ElementWrapperPart
, and configure it to use our "CompanyInfo" blueprint element.
Let's do a quick tutorial to see that in action.
First, go to the new Elements menu item and hit the Create button:
Orchard will ask you to pick a Base Element. We'll go with Html:
When creating an Element BluePrint, we need to provide the follwoing information:
The display name is used when presenting the user with available elements.
The element type name is a technical name used to uniquely identify an element.
The element category is used when the element is rendered as part of the element toolbox in the layout editor.
I specified the following values:
Next we'll see the element-specific editor. This will be the HTML editor, since we chose the "Html" element as the base element.
After hitting Save, we now have our own little "Company Info" element, ready to be used.
Add it to "Master Layout" created earlier:
After adding the "Company Info" element, our master layout and child pages will look something like this:
What's interesting is that no matter how many times you add this element to whatever layouts, whenever you change the blueprint element's contents, those changes will be visible instantaneously.
Note: changing a Blueprint element will cause its changes to immediately appear on published pages.
Next, we'll turn the "Company Info" element into a widget. To do so, go to Content Definition -> Content Types -> Add, and use the name "Company Info Widget" as the display name and "CompanyInfoWidget" as the technical name.
Attach the following parts:
After hitting Save, uncheck the following settings:
Set Stereotype to: Widget
Expand the "Element Wrapper" part settings, and enter the element type name of our "Company Info" element: CompanyInfo and Hit Save to persist the changes.
To test this new widget, go to Widgets and add a new widget to the AsideSecond zone of the Default layer, choosing the new "Company Info Widget".
You will not see any element specific editor, but when you navigate to the front end, you'll see the new widget shine bright.
Using element blueprints you can add multiple widgets of the same type without having to duplicate content.
Another technique to "reuse" content is to use the "Content Item Widget", which lets you select one or more content items to render in place.
This concludes the highlevel overview of the new Layouts feature. I'm very excited about this one with all of its options, flexibility and extensibility.
The new Dynamic Forms module leverages Layouts and lets the user compose forms using form elements, effectively turning the layout editor into a forms builder.
This very website is powered by the Layouts feature - this is how our homepage looks in edit mode:
In the next post, we'll take a look at Dynamic Forms.
Stay happy!
Initially, I thought the layout templating was supposed to be layouts created via "Manage Layout Content" @ /Admin/Contents/List/Layout but found I couldn't extend those in children the same as templated content. Very helpful article! Also, the fluid element category is an especially nice touch I didn't pick up previously. Thanks!
It seems to me that the dynamic layout is more suited for the static websites. I wonder how could we use this great module to build a more dynamic website like you did in your famous webshop tutorial.
I tried a little bit to use dynamic layouts to build a simple webshop but gave it up :-(
@Alex - The Layouts feature enables you to put elements onto a canvas, nothing more. When building a webshop, you could use Layouts to place certain commerce elements here and there, but you'd have to write such elements yourself first, and they would add to your commerce module - there's no way you can implement a webshop with just the out-of-box- layout features and no coding. Hope this clarifies a bit.
@Sipke, I didn't expect to do it without coding. I tried to use my existing parts and shapes and render them inside the layout. I guess I have to spend more time to understand the concept and find out how to use dynamic layouts. I would appreciate it if you could give us a few hints and point us to the right direction. Anyway, thanks for your effort with this great module. (Daniel, too) Thanks in advance.
Great article yet again!
In the part of Bootstrap, I assume by this:
You mean the Views/Elements/Grid.cshtml and Views/Elements/Column.cshtml?
@Sipke Schoorstra, Thank you so much. The Layout feature is powerful. But unfortunately we cannot use it because it is not fully localizable for clients. Please consider this issue specially about this feature because this feature must be available for clients.
Just a note for readers of this post, the modifications you make for Bootstrap list the older file locations for files. I believe the appropriate location would be ~/Views/Elements/FILENAME.cshtml (replace with Grid, Column, etc.)
I am wondering, @Sipke, whether I can completely override the layouts. I am using a bootstrap/angular dashboard. Each section/space has some differences but still uses the container, etc. elements of bootstrap for a grid. Essentially, I want to create separate master layouts for each "space" in the dashboard, which has some unique elements unto itself.
The layout of your blog make me nervous! Half of space just leaved empty. It feels like I'm reading blog in a small screen! Why just don't make it 70/30? :)
Your example views to use bootstrap classes don't work for us. The method "ToInt32()" is not accessible at that point and the property "Model.ColumnSpan" is always null. Also, the class "container" should not be added there, because you usually have this class already in your bootstrap theme. I also don't see why you make this override of Column.cshtml so much different from the original. I got everything to work with these overrides:
Column.cshtml: @using Orchard.DisplayManagement.Shapes @using Orchard.Layouts.Elements @using Orchard.Layouts.Helpers @{ var element = (Column) Model.Element; var columnSpan = element.Width; var columnOffset = element.Offset; var columnOffsetCss = columnOffset > 0 ? "offset-" + columnOffset : default(string); var tagBuilder = TagBuilderExtensions.AddCommonElementAttributes(new OrchardTagBuilder("div"), Model);
Thanks everyone. The examples have been updated.
Do u have any workaround for sorting, search and paging features in the Layout - Grid in this 1.9 version. It would be great help, as i am working the same on 1.6 by adding custom content part, but still not completed.
Brilliant, this also works great with Zurb Foundation & the appropriate edits to the shapes (row, columns, large-x large-offset-x etc). Thanks for this exciting module.
Is there a way (or a plan) to define a default layout template for a particular content type? For example, to make it especially easy for editors, I might define a layout template with a Grid/Row/HTML element & have a new "Page" use that layout by default, rather than the editor having to select it from the dropdownlist? In this way the page would be ready to go without having to drag & drop a grid, then a row etc. It would resemble the more simple Page content type with a BodyPart. So basically, pre-set the TemplateId...
Claire: I think that's a brilliant idea. I'm adding it to our backlog.
Please note that today you can define a default JSON string on the content type level for the LayoutPart, whcih will be used as the default layout configuration. We use this for example when creating a new Form content item (Dynamic Forms), which lets you start with an empty Form element and a Submit button.
Having an additional setting to configure the layout template would indeed make for a nice addition,
Sorry for what I imagine is a simple question for most to answer. Fairly new to Orchard. How would one extend the elements found in the layout functionality? Specifically I'm trying to create bootstrap elements such as container-fluid or jumbotron.
Any help is much appreciated, thank you!
Your write up is EXACTLY what I was looking for! Thanks
Hi
This new layout Feature Looks very promising. I upgraded my Orchard 1.8 site to 1.9 and enabled the module. Currently my pages have a body and a layout and therefore the concent is rendered twice. Did I miss something during the update of the code? Is there a out-of-the box Migration to convert the Body into a layout?
Thanks
Marc
I have been using Layouts intensively for a few days, experimenting with a one-page website theme based on bootstrap and have found it very good. However, I think it could be extended in a few areas: 1. Introduce drag and drop across the hierarchy, not just reordering of siblings. It is extremely tedious to have to reconstruct a complete Grid just because I need to enclose it in another div, for example. 1. Enable tabs to be selectable. It is too hard to click on the border; the tag (Row, Canvas, etc) should be selectable too. 1. Ability to save Layouts and reuse them. BTW: your images have stopped displaying in the tutorial.
All the images are missing in this article :(
@Dave: Adressing your comments in order:
@Matthias: We had a little mishap when migrating from one Azure subscription to another. Sipke is working on restoring the images for this blog post.
Hi,
could the broken image links please get fixed?
I have to ask what feels like a dumb question... where IS the content in the editor in 1.9? I upgraded my site from 1.8 to 1.9 and when I try to edit a page, everything is blank... even the code view? Do I have to do something to migrate my content to the new layouts? .. Is this something that the theme is responsible for?
Any chance that someone can add the images again? Would be very helpful. Thanks!
great feature! now, when trying the first time to use 'use existing layout' to get exactly the same layout I'm NOT able to edit it!? I.e. I cannot see the layout like grid, row, coloumn etc NOR e.g. open a HTML tag to be able to update the content. I guess I miss something simple but can't figure it out thanks for your time and help ed
ref comment 07/07/2015 well, I found a solution by plain 'clone' the CI! Now I'm asking myself what for do I use the 'use existing layout'!?! (which doesn't allow editing - see ref comment!) happy to receive the purpose 'use existing layout'! thanks ed
Just to add to the chorus, could we please get the images back on this? I keep coming back to this page when doing google searches and I can't help thinking that a lot of queries would be resolved if the images were there.
Can we please fix the images issue. It's difficult to follow the blog without images being displayed.
I hope you can fix the images issue as soon as possible. This is helpful article. Also can you please write a blog post about migration from BodyPart to LayoutPart?
Great feature and a very helpful post explaining how to use layouts. One question...
Is there currently or in future any plans to support exporting layout elements? I'd love to be able to define a recipe that sets up a bunch of commonly used layout elements.
Hi how we can use Widget in layout?
The images are broken..
:( Images are not displayed. Could you please fix it?
I've only just discovered this feature because I haven't done any new sites, just upgraded existing sites and that keeps the BodyPart it seems.
Really excited but finding it hard to follow along without the images :(
As everyone has been begging for them for so long in all of the blog posts I'm guessing its not going to be an easy fix? :/
If its just a tedious case of matching them back up to the folder structure or something and you don't have time to do it maybe somebody from the community can get involved? This site is such a great resource for Orchard its a shame to see it fall into disrepair.
Sorry for taking so long everyone. I was finally able to put myself down and restore the images of this post. I appreciate all the kind feedback on the article, thank you!
ref to comment 7/7 and 7/8 2015 well I found the solution by using the 'layout template' feature; finally it's always easy
This is a fantatsic accompaniment to your talk at the Orchard Harvest 2015. I found the way it explains the layout feature's relationships with widgets and zones particularly useful. Just need to get this on the Orchard documentation site now ;) Does anyone else find the ".table" class (equivalent of bootstrap's container class) conflicts with bootstrap's ".table" class and cause some strange negative margins?
Wonderful! So simple. Thanks for the info, you made it easy to understand. BTW, there is an online service through which you can fill out a Bankruptcy B10, the fillable blank is here
http://goo.gl/eX9bPh
Probably a really stupid question, but where are Orchard.Layouts/Views located? Would this need the source code version or webmatrix web ready? I'm using Orchard 1.10.1. Thanks
Hi David, you can find those views in the Views folder of the Orchard.Layouts module. This folder consists of a few subfolders, one of them being Elements. You should be able to find them in both the source code version as well as the web package (WebMatrix). Let me know if you're still having issues finding the views you're looking for.
When I make a change to an existing layout, even a small change, the results are pretty unpredictable for the pages that already use those layouts. Elements are often moved into other rows/columns. Is there something I should be doing differently?
I am trying to use the bootstrap version 4 and updated the Grid.cshtml and column.cshtml and was able to see the correct layout when viewing the page but when editing the page in admin the bootstrap classes is not working. Can anyone help me to fix this issue ?