Rendering Backbone view into multiple elements with different configurations - jquery-mobile

I have a html page with 3 jquery-mobile page widgets. Each page widget has the same header with a slightly different configuration for sub links. I want to create the Header as a BackboneView and render it for each page widget. Each page widget has it's own view as well. The page template looks like this:
<body>
<div id="news" data-role="page">
<header class="header"></header>
</div>
<div id="updates" data-role="page">
<header class="header"></header>
</div>
<div id="stuff" data-role="page">
<header class="header"></header>
</div>
</body>
The view for the first page, in this case being news view, gets rendered first. This page creates an instance of the header view. The problem arises when working with the header.
1) How do I target the header specifically for the first page, "#news header" while keeping it flexible enough for me to call it again with a different set of parameters when I am ready to load the updates page?
2) When I'm ready to load the updates page, it will have a different set of configurations that need to target "#updates header". Therefore I don't want to hardcode tagName on the view.
3) How do I pass the first instantiated header to the rest of the views? Or am I thinking about this all wrong and should I be extending a base Header view as a template for each of my pages which come baked in with a set of configs?
The only thing that is different between each header is a class name it will attach to an element in the rendered view and a few anchor links it makes for the page. For this, I am trying to reuse the view as much as possible to have a light footprint.
Note: Not sure if it matters but I'm using requirejs. Maybe there is a suggested way to create a View and always have it reused when necessary since requirejs handles modules as singletons?
Thanks!

Use an overview like appView.js. It will be in charge to render all the subviews.
In appView (you'd need to require your subviews in this super module, HeaderView):
initialize: function() {
this.$news = $('#news');
this.$updates = $('#updates');
this.$stuff = $('#stuff');
},
render:function() {
var newsView = new HeaderView(param1,param2);
this.$news.append(newsView.render().el);
// do the same for your other subviews
}
In your subviews (lets say NewsView)
initialize:function(param1,param2) {
this.viewclass= param1;
//set the other things you need here
},
render: function() {
this.$el.html("my content here..model/template/anything"));
this.$el.attr('class',this.vewClass);
}
Remember that the point is to have an overview creating new SubViews and calling the render(). I hope it helps.
Edit: If you are waiting for some data to load a specific subview, use a promise. If you are waiting for a collection to finish to fetch use something like that
collection.fetch(function() {
success:function(res,model) {
new subView(model);
}
}

Related

Shared content between templates

I would like to share content (essentially blocks of html) between templates.
For example, suppose I have a common footer section with a graphic or two, text and links to 'about us', 'contact us' and so on.
I have different templates for different page layouts, but they all require this footer.
So far I can think of three ways :
Nesting templates : ie have a master one which has the footer content, then a child one for each layout, then the actual page template, but this could get tricky if some pages need a different footer
Using a Partial View to hold the footer content and using #Html.Partial() to pull in the partial view on the various templates
Create a settings document with the footer content and use Umbraco.Content() to fetch the footer property
Is any of these the recommended process (and are there any pitfalls?) or is there a better way?
I would normally do one of the following:
Have properties on the homepage for the footer links etc (in a separate tab) and pull in the values into the footer partial, this way you only have to set it once, rather than having it on every page
Have a Site Settings node at the same level as the home page and pull the values from there into the footer partial
That seems to be fairly standard from most of the Umbraco sites that I've worked on. I wouldn't have all of the properties on each page, unless you need a unique footer each page for some reason.
For example, lets say you add a tab called "Footer Settings" to the Home Page DocType with a single string property with the alias "copyRightNotice" and then you want to display that in a partial, your partial might look something like:
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#{
var rootPage = Model.Content.AncestorOrSelf(1);
<h3>#rootPage.GetPropertyValue("copyRightNotice")</h3>
}

Extend element beyond _Layout container MVC ASP.NET (preferred method?)

I'm doing a little experimenting with MVC / Bootstrap / ASP.NET...
Specifically I'm trying to understand a best practice to allow an element to extend past its container based on a given logic, in this case based on the loaded view. (I've read through the threads on showing elements based on a Role membership as well).
I'm trying to replicating the layout shown here: URL To Sample. It has a bootstrap carousel and I like the placement extending the entire width but only showing on the Index (Home) page. Implementing this outside of the classic MVC structure is trivial.
With MVC we have the shared _Layout.cshtml and the container where views are loaded with ...
<div class="container body-content">
#RenderBody()
</div>
It seems the carousel needs either
be placed on the _Layout page and hidden if the loaded view is not the Index page or
be placed on the Index page and allowed to exceed the width of the container
I've tried what I've been able to find in threads but haven't been able to replicate this layout cleanly. Can someone please give a bit of direction?
You could stretch it with css, or a cleaner solution could be to put it in its own (optional) section:
in _Layout:
#RenderSection("carousel", required: false)
<div class="container body-content">
#RenderBody()
</div>
in your front page/home (index) file:
#section carousel {
// code for carousel
}
As commented by #Alex, if your home page is significantly different from the other pages, you can use a separate layout file. To do this, just set the "Layout" global string like this;
in your front page/home (index) file:
#{
Layout = "~/Views/Shared/_FrontPageLayout.cshtml"; // to use a separate file
Layout = null; // to not use a layout file
}

Passing arguments between MVC views to match an item from a data source available in the model

I have a view that renders a side bar for a content page. The side bar can be rendered several times on a single page. The page's layout defines several content sections (or, positions, in Kooboo's terminology) which are, in an actual page, bound to specific views. In each such view I need to optionally render a side bar by redering the general-purpose side bar view.
Side bars' content is stored in Kooboos database. I'm using a specific content type which has, for the sake of simplicity, the following two fields:
Position — the ID of the position in the page, which matches an ID of a position defined in the layout
Content — an HTML fragment that constitute's the side bar's actual content
The side bar view's logic should be as follows: from all side bar data bound to the current page select a single item with a Position matching a position passed from the outer view as an argument, and, if found, render it. The problem is, I can't figure out a way to pass arguments into a view
Sample layout fragment:
<!-- Header section -->
<section>
<div class="section-content">
#Html.FrontHtml().Position("Header")
#Html.FrontHtml().Position("HeaderSectionContent")
</div>
</section>
<!-- Main section -->
<section class="even">
<div class="section-content">
#Html.FrontHtml().Position("MainSectionContent")
</div>
</section>
Sample view bound to the Header position:
<div class="header-container">
<h1 class="page-title" #ViewHelper.Edit(ViewBag.Solution, "Title")>
#ViewBag.Solution.Title
</h1>
<!-- How to pass "Header" string as an argument into the Controls.Sidebar view? -->
#Html.FrontHtml().RenderView("Controls.Sidebar",ViewData)
<h2 #ViewHelper.Edit(ViewBag.Solution, "Perex")>
#Html.Raw(ViewBag.Solution.Perex)
</h2>
</div>
The intended general purpose side bar view Controls.Sidebar:
#if (ViewBag.Sidebars != null)
{
// How to retrieve an argument and select the matching side bar data?
var sidebar = ViewBag.Sidebars ... ;
if (sidebar != null)
{
<div class="side-bar">
<h3>#item.Title</h3>
#Html.Raw(item.Content)
</div>
}
}
At the end of the day I need to be able to render this view several times, and conditionally render several side bars in respect to data availability.
I was looking into the Parameters definitions available in the view editor, but it seems this provides access to query string parameters, which is not a mechanism I could (would like to) leverage. Kooboo documentation is lacking any information related to this topic.
There are at least two ways to pass some parameters from one view into another in Kooboo:
First you can store your parameter value in the parent view like this:
Context.Items["ParameterName"]=value;
or like this:
var customViewData = new ViewDataDictionary();
customViewData.Add("ParameterName", value);
Then you can call rendering of a child view:
#Html.FrontHtml().RenderView("ChildViewName", ViewData) //a default ViewData passed
or as following, respectively:
#Html.FrontHtml().RenderView("ChildViewName", customViewData)
On the receiving side in ChildViewName you simply fetch the parameter value either thus:
var value = Context.Items["ParameterName"];
or thus, respectively:
var value = ViewData["ParameterName"]; // NB: don't forget to cast parameter to a proper data-type, because ViewData is not processed same smoothly as ViewBag would.
Both ways work just fine for this purpose.

Can I conditionally render partial views in _Layout.cshtml?

Suppose I have a _Layout.cshtml where I render a left sidebar, which is common to every page of my website.
Something along these lines - a menu, for example
<div id="left-sidebar">
#Html.Action("_MenuView", "LeftSideMenu")
</div>
A feature I would like to have would be to add another partial view, but only display it in certain sections of the website.
For example, in the blog section I may want to display a list of post categories or a treeview of the posts.
<div id="left-sidebar">
#Html.Action("_MenuView", "LeftSideMenu")
#if ("???")
{
#Html.Action("_BlogTreeView", "BlogEntries")
}
</div>
How could I do that? I know that I want to display "_BlogTreeView" if the view I'm rendering is returned by BlogController ... where do I go from there?
In your layout, add this section
#RenderSection("blogEntries", false)
Then in every view where you want to show the partial view add this:
#section blogEntries {
#Html.Action("_BlogTreeView", "BlogEntries")
}

Scrolling down a page after rendering in Rails

Is there a way to scroll or jump down a page after rendering it?
Specifically, in my controller action, there are some situations where I'll want to send the user to a particular place on the page. If it were just a link from another page, I'd probably use a URI fragment identifier - "http://blorg.com/page#id" - but this needs to be dynamically generated depending on some condition.
Maybe I need to use JavaScript (Prototype) somehow, but I don't know how to call the function once the page is done loading, especially from the controller.
You should really do this type of thing in your view. In your controller you should evaluate your condition to determine the part of the page you want to show, then pass the result into the view. You can then be able to use this information in your view to add a small piece of javascript at the bottom of the page that does something like the following. Of course this doesn't help you if the user has javascript turned off ;)
Controller code:
def index
# evaluate the condition
#section = (rand*10).to_i
end
View view code:
<div id="#section1">some stuff</div>
....
<div id="#section9">other stuff</div>
<% if #section>0 %>
<script type="text/javascript">
// <!--
document.location.hash="#section<%= #section %>";
// -->
</script>
If you are using jQuery, an an answer could be as follows:
$("body").scrollTop($("#my-element").position().top;
Or if you want to be really fancy (recommended), you can animate the scroll top like so:
$("body").animate({scrollTop: $("#my-element").position().top},1000);
you can have browser scroll to a position down the page by including a fragment part in the url that links to the page. e.g. http://example.com/index.html#section3 will scroll the page to the element with 'id' section3. you can use that id on a link, paragraph, etc. the browser will make sure the element is visible after the rendering.

Resources