I have a predicament that I am not quite sure how to overcome. I do not know what is the right way. I am building a website and I was given a template to integrate with my server code. The problem lies in how the template is outlined. Let me show you an example.
<body>
<div class="breakpoint active" id="bp_infinity" data-min-width="588">
<div id="header">full page header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
<div class="breakpoint" id="bp_587" data-min-width="493" data-max-width="587">
<div id="header">mobile header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
<div class="breakpoint" id="bp_492" data-max-width="492">
<div id="header">mobile header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
</body>
I am trying to setup my MVC5 Views in a way that does not repeats common code. The problem that I am facing is that the header and footer div are common code from page to page and the body changes. The second problem is that each page has different number of breakpoints. Here is a second page to show what I mean:
<body>
<div class="breakpoint active" id="bp_infinity" data-min-width="588">
<div id="header">full page header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
<div class="breakpoint" id="bp_587" data-max-width="587">
<div id="header">mobile header content</div>
<div id="body">some stuff</div>
<div id="footer">some stuff</div>
</div>
</body>
So the Layout page is now tricky to setup because I can't just say:
<body>
@RenderBody
</body>
One of the solutions I thought of was to use Sections, something like this:
<body>
@RenderBody
@RenderSection("Breakpoint-1", false)
@RenderSection("Breakpoint-2", false)
@RenderSection("Breakpoint-3", false)
</body>
Now each page would be along the lines of:
@section Breakpoint-1
{
<div class="breakpoint active" id="bp_infinity" data-min-width="588">
@{ Html.RenderPartial("full-page-header"); }
@{ Html.RenderPartial("full-page-body"); }
@{ Html.RenderPartial("full-page-footer"); }
</div>
}
@section Breakpoint-2
{
<div class="breakpoint" id="bp_587" data-max-width="587">
@{ Html.RenderPartial("mobile-page-header"); }
@{ Html.RenderPartial("mobile-page-body"); }
@{ Html.RenderPartial("mobile-page-footer"); }
</div>
}
A problem that I see with above code is that if the header now needs to have 5 breakpoints instead of 2, I need to go and modify it everywhere.
Is there a better way to do this? Is what I thought of the best solution for my scenario?
EDIT: To clarify. There are multiple brakpoints in the HTML because only one of them is active at a time. When page hits a certain width, 1 the currenct active breakpoint gets hidden and the new one becomes visible.
... are the mother of all....
This is a basic example, there are plenty of other approaches to try and plenty of other tweaks you can make
Controller Let's call this BreakpointController
public ActionResult Index()
{
var model = new List<BreakpointViewModel>();
// populate model
return View(model);
}
ViewModel
public class BreakpointViewModel
{
public string BreakPointId { get; set; }
public int? MinWidth { get; set; }
public int? MaxWidth { get; set; }
public string Body { get; set; }
public bool IsActive { get; set; }
}
View
This should be your index.cshtml
(or whatever you want to call it)
@model IEnumerable<WebApplication1.Models.BreakpointViewModel>
<div>
<h1>A header!</h1>
</div>
@Html.DisplayForModel()
<div>
<h4>A footer!</h4>
</div>
DisplayTemplate * Thou shalt live in the folder containing views for the controller (or Shared) * Thou shalt live in a subfolder named 'DisplayTemplates' * Thou shalt be named {ModelName}.cshtml
in the end, the folder structure should look something like this:
Views
|-- Breakpoint
| |-- DisplayTemplates
| | +-- BreakpointViewModel.cshtml
| +-- Index.cshtml
And BreakpointViewModel.cshtml should look like this:
@model WebApplication1.Models.BreakpointViewModel
<div class="breakpoint @(Model.IsActive ? "active" : null)"
id="@Model.BreakPointId"
@(Model.MinWidth.HasValue ? "data-min-width='" + Model.MinWidth + "'" : null)
@(Model.MaxWidth.HasValue ? "data-max-width='" + Model.MaxWidth + "'" : null)>
@Html.Raw(Model.Body)
</div>
Note the minwidth/maxwidth lines in the div. Not required, just how I would personally deal with the widths.
<div>
<h1>A header!</h1>
</div>
<div class="breakpoint active"
id="bp_1"
data-max-width='720'>
<div>Hello World!</div>
</div>
<div class="breakpoint"
id="bp_2"
data-max-width='720'>
<div>Another Breakpoint</div>
</div>
<div class="breakpoint"
id="bp_3"
data-max-width='720'>
<div>Third Breakpoint</div>
</div>
<div class="breakpoint"
id="bp_4"
data-max-width='720'>
<div>Fourth Breakpoint</div>
</div>
<div>
<h4>A footer!</h4>
</div>
DisplayTemplates are your friend. If your sections are going to be the same, you can put the relevant information into a ViewModel, then pass the List<ViewModel>
to the DisplayTemplate. The MVC engine will then use the DisplayTemplate for your ViewModel to fill out the needed code for each section.
You only need code your DisplayTemplate for your ViewModel once.
I don't have any sample code up at the moment, but if you need further help, comment on this and I'll break some out over the weekend.