Programming and stuff

A client I’ve been working with for a while requested that a page with quite a lot of different ‘widgets’ on it, needs to be able to be changed by them on a whim.  By ‘changed’, I mean that they can change the layout, styling and positioning of these ‘widgets’.

The original page was using WebForms with UserControls and WebControls etc, and would have been a pain to somehow allow some customisation, so I started to think about how to do it with NancyFX and knocked up a small sample app.

Basically, I have a View Model, SiteLayoutSettings, that describes which section on the page these widgets will go into.

public class SiteLayoutSettings
{
    public string LayoutName { get; set; }
    public List<Section> Sections { get; set; }
}
 
public class Section
{
    public int Index{ get; set; }
    public List<Item> Items { get; set; }
}
 
public class Item
{    
    public string PartialName { get; set; }
    public dynamic Data { get; set; }
}

The Item class is the interesting one, as this described which partial view to load up for the widget and then the data that gets passed to it. At design-time though, this data is unknown, so I’ve set the type to be dynamic.

The setup side of the system then just has to store how they would like the page laid out, so that on the display side this View Model can be populated.

For this sample app, I’ve hardcoded one as follows:

var siteLayout = new SiteLayoutSettings() 
{ 
    Layout="Something",
    Sections = new List<Section> 
    { 
        new Section
        { 
            Index = 0,
            Items = new List<Item> 
            {
                new Item 
                {
                    PartialName = "_oneType",
                    Data = new OneTypeOfData 
                    { 
                        Url = "bbc.co.uk", 
                        Name = "BBC" 
                    }
                },
                new Item
                {
                    PartialName = "_otherType",
                    Data = new AnotherTypeOfData 
                    {  
                        Title = "Dave", 
                        Value = "10" 
                    }
                }
            }
        },
        new Section
        {
            Index = 1,
            Items = new List<Item>
            {
                new Item
                {
                    PartialName = "_otherType",
                    Data = new AnotherTypeOfData 
                    { 
                        Title = "Pete", 
                        Value = "20" 
                    } 
                }
            }
        }
    }
}

 

The two ‘data’ classes are as follows:

public class OneTypeOfData
{
    public string Name { get; set; }
    public string Url { get; set; }
}

public class AnotherTypeOfData
{
    public string Title { get; set; }
    public string Value { get; set; }
}

What I then do in my module’s Get is choose the view to return (based on which overall layout the client has selected, probably stored in a db), and pass in the layout settings:

return View["ThreeColumnLayout.cshtml", siteLayout]; 
 
or
 
return View["GridLayout.cshtml", siteLayout]; 
 
etc

 

In the views, in each section, I then iterate over the Items collection in each section, rendering a partial with the name and the data for each one:

@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<NestedTest.SiteLayoutSettings>
@{
    Layout = "Master.cshtml";
}

<h1>Layout is @Model.Layout</h1>

<div section="1" style="border:1px solid Red;">
    <h1>section 1</h1>

    @foreach (var item in Model.Sections[0].Items)
    {
        @Html.Partial(item.PartialName, item.Data);
    }
</div>

<div section="2" style="border:1px solid Green;">
    <h1>section 2</h1>
    @foreach (var item in Model.Sections[1].Items)
    {
        @Html.Partial(item.PartialName, item.Data);
    }
</div>

 

_oneType.cshtml

@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<NestedTest.OneTypeOfData>

<h2>Url = @Model.Url</h2>
<h2>Name = @Model.Name</h2>

 

_anotherType.cshtml

@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<NestedTest.AnotherTypeOfData>

<h2>Title = @Model.Title</h2>
<h2>Title = @Model.Value</h2>

 

What I love about this approach is the flexibility of it. As long as I’ve got some data and a view, I can push anything into one of these layout pages.  And the layout pages can be crafted in any way I like, all I have to do is put in the inline code to render out the section (which, will shortly be in a class of it’s own, RenderWidgetSection(1) or something).  But the greatest thing? Not a line of server side generated html in sight, which would have been my first thought had I gone down the WebForms route.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Tag Cloud

%d bloggers like this: