How do you set up a page to use a different template in Zotonic? - zotonic

I would like to have alternative templates for each section of my website.
How do you set up a page to use a different template in Zotonic?

Here is how you could render the about page with a custom template:
{about, ["about"], resource_page, [ {template, "about.tpl"}, {id, page_about}]}
If you add the above dispatch rule to your site's dispatch rules (found at yoursite/dispatch/dispatch) it will render a page with the unique name of page_about using about.tpl.
You can set the unique name for a page in the advanced tab of the page in the zotonic admin.

Good practice is to set the page_path property to the url you define in the dispatch rule. So that the page_url of the (in the example) page_about is also "/about".

Related

Show header permalink on hover (pelican)

How do I get a clickable "permalink" to show on hover (for e.g. h2 headers) similar to this.
I'm using the pelican framework and am writing in restructuredText. I can't figure out where in the stack to tweak to enable this (pelican? rst? jinja2?)
It's called a label. Usage is documented under the ref role.
To support cross-referencing to arbitrary locations in any document, the standard reST labels are used. For this to work label names must be unique throughout the entire documentation. There are two ways in which you can refer to labels:
If you place a label directly before a section title, you can reference to it with :ref:label-name. For example:
.. _my-reference-label:
Section to cross-reference
--------------------------
This is the text of the section.
It refers to the section itself, see :ref:`my-reference-label`.
Edit
For Pelican, there is a plugin called headerid that will render permalinks.
You can get that through the options of the Markdown TOC extension.
Just set the permalink option to True in your pelicanconf.py:
MARKDOWN = {
'extension_configs': {
'markdown.extensions.toc': {'permalink': 'True'}
}
}

using href or routerlink with #

I'm fairly new to changing paths / position of page so I would like a little help on this.
Say, when a button is clicked, I want to scroll down to another portion of the page. (where id of that section is 'xyz') however, I'm using an entirely different component to access that section.
If I were to use href, I can easily do : href="/app/appid#xyz"
however, if appid is a variable retrieved from the ts file, how can I insert it into my href?
It's easier to to use [routerlink]="['app', appid]" but how can I insert the "#xyz" into my string?
Or is there a completely separate and easier functionality I can use?
Thank you
Add the frament attribute:
<a [routerLink]="['app', appid] fragment="xyz">Link</a>
https://angular.io/api/router/RouterLink

Render different partial templates in EpiServer

I have a page partial that is supposed to render inside a ContentArea when the page is added there. This works perfectly, but now I have two different ContentAreas on two different pages and I want the same child page added to those to render different on each parent page.
I get that I could in some way use a Tag when rendering the partial to differentiate between the ContentAreas:
#Html.PropertyFor(m => m.MyBlockProperty, new { Tag = RenderingTags.Sidebar })
#Html.PropertyFor(m => m.MyContentArea, new { Tag = RenderingTags.Sidebar })
But then, in my SomePage.cshtml (which is my partial view), do I get a varaible or something here so I know which Tag was asked for? Or is there some naming convention like SidebarSomePage.cshtml so that I can define multiple partial templates? Do I have to create a controller to deal with this? It seems unneccessary to me, I just want to change the html a bit depending on page...
Create a PartialContentController<T> and then use the TemplateDescriptorAttribute to specify the tags you wan't to use. Then use PropertyFor as Johan explained in the view.
From the EPiServer documentation
The template you choose to render a content instance depends on the specific context such as channel and tagging. For a template to be automatically registered it has to implement EPiServer.Web.IRenderTemplate (where T states which model it can render). If you use a base class for your template like PageBase, ContentControlBase, BlockControlBase, PageController, PartialContentController or BlockController, then you do not need to explicitly implement the interface because that is done by the base class. In addition, you can use the TemplateDescriptorAttribute to specify more details about the template such as tags and inheritance, more information on that topic later.
I'm pretty sure you can access the tag from the ViewData dictionary in your view (or controller) like this:
#ViewData["Tag"]
You can also pass any other setting to the view
#Html.PropertyFor(m => m.MyContentArea, new { Tag = RenderingTags.Sidebar, RenderThisPartialDifferently = true, ShowHeading = false })
And then access them:
#ViewData["RenderThisPartialDifferently"]
#ViewData["ShowHeading "]
And then you have the option to have a controller in between and render a completely different view.
Pretty sure there is a naming convention for tag views as well. What I do know for sure though, is that you can put a view with the same name as the tag in /shared/displaytemplates. But that's not what you're asking for now.
Also addition to all answers, you can use template registrator to register additional templates for specific tags.
[ServiceConfiguration(typeof(IViewTemplateModelRegistrator))]
public class TemplateCoordinator : IViewTemplateModelRegistrator
{
public void Register(TemplateModelCollection viewTemplateModelRegistrator)
{
viewTemplateModelRegistrator.Add(typeof(MyBlock), new TemplateModel
{
Tags = new[] { RenderingTags.Sidebar },
AvailableWithoutTag = false,
Path = BlockPath("Some-Other-Template.cshtml")
});
}
}
This will make sure that if block is rendered "inside" RenderingTags.Sidebar context (for instance via Html.PropertyFor(...., new { tag = RenderingTags.Sidebar })) file Some-Other-Template.cshtml will be used.
AlloyTech has sample code there.

How can I pass a value when creating a new tab panel with CSJS

I want to create a new tabbed panel for the Dojo tab container using CSJS like:
dijit.byId('#{id:djTabContainer1}').createTab({ tabTitle: Math.random()});
The default tab panel has an panel that will use the iframe tag and I want to pass in the above call the src html attribute to the panel.
Question : I can specify a url to load in the iframe. Is there a way to pass this?
It seems like the createTab only does certain tab related parameters like action and tabTitle.
Howard
The syntax is somewhat obscure here. Starting with the code in the ExtLib demo app:
XPagesExt.nsf/Core_DynamicTabs.xsp
Change the script in button4 to:
dijit.byId('#{id:djTabContainer1}')
.createTab({
"newName":'Tab'+Math.random(),
"newHref":'/XPagesExt.nsf/page5.xsp'})
to match the syntax you're requesting.
And, in the tab that's referenced by defaultTabContent, change the title and href to use those passed URL parameters:
<xe:djTabPane xp:key="doc" id="djTabPane2"
title="${javascript:/*load-time-compute*/param.newName}"
href="${javascript:/*load-time-compute*/param.newHref}"
It will create the tab and will attempt to load the href contents. I'm not seeing it as an iframe though - it's just a container div.

ASP.Net MVC: How to dynamically generate a meta tag based on the content of the url?

Here is the idea:
When the user wants to see /controller/action, then I want the page to have a "robots" meta tag with its value set to "all".
When the user wants to see /controller/action?sort=hot&page=2 (i.e. it has a query string), then I want the page to have a "robots" meta tag with its value set to "noindex".
Of course this is just an example and it could be another tag for the existence of this question.
At what stage in the MVC architecture could I place a hook so that the view generates the tag I want in the master page?
I do something similar for generating page titles and it works well. Put your tag in your masterpage as normal:
<%= Html.Encode(ViewData["Title"]) %>
Then subclass ActionFilterAttribute and override OnActionExecuting. From there you get access to the controller context and can set your viewdata to whatever you want.
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.Controller.ViewData["title"] = "whatever";
}
last step is to put Attribute your controllers that you want to use the filter context. You can inherit from a base controller if you want to add the attribute to all classes. There are also overloads if you want to pass parameters. In my app. I actually pass the page title.
Hope that helps.