generating page title with razor script - umbraco - razor

So I am trying to create a script whereby depending on the document type of the page a certain pre-defined title tag format will appear, if there is nothing already written in an overwriting custom title input. I have inserted the macro within the title tag on my master template but keep on getting an Error loading Razor Script message .
Html
<title>
<umbraco:Macro Alias="NewPageTitle" runat="server"></umbraco:Macro>
</title>
Script -
#inherits umbraco.MacroEngines.DynamicNodeContext
#using umbraco.MacroEngines
#{
if(String.IsNullOrEmpty(#Model.tabName.ToString()) == false )
{
#Model.tabName
}
else if(#Model.DescendantsOrSelf("Country"))
{
<text>
Holidays in #Model.Name
</text>
}
else
{
#Model.Name;
}
}
Any help would be greatly appreciated.

Try this code out. The problem with your original code is that you were using "#Model.DescendantsOrSelf("Country")" as a boolean, and it is a list. I also removed your comparison for if(String.IsNullOrEmpty(#Model.tabName.ToString())).
Also, if you add ?umbDebugShowTrace=true to the end of your URL, you can get some valuable debugging information. There is a Chrome Extension called "Umbraco Debug" that I use to quickly access that query string and information. You may find it useful.
#inherits umbraco.MacroEngines.DynamicNodeContext
#using umbraco.MacroEngines
#{
if(String.IsNullOrEmpty(#Model.tabName.ToString()))
{
#Model.tabName
}
else if(#Model.DescendantsOrSelf("Country").Count() > 0)
{
<text>
Holidays in #Model.Name
</text>
}
else
{
#Model.Name;
}
}

its very simple just add following code into your title tag
#Umbraco.Field("pageName")
will display pageName,you may also add custom properties from document type.
e.g. you have added new property like "metaKeywords" with value "html,javascript,xml",fetch that values as following way...
#Umbraco.Field("metaKeywords")
even you don't need to add custom properties in your model

Related

How can I use Render sub-template in a C# template in a Content module that uses lists within lists?

2SXC 10.25.2 / DNN 9.3.2
I have a 2sxc module that uses a C# template with "list" enabled. I have a content type called "pathway" and inside that I have 2 entity picker fields for "first step sessions" and then "next step sessions". These entity pickers use a "session" content type. Inside each of those "session" content types I also have an entity picker for "speaker(s)". All in all, it's a setup that I have lists within lists within lists.
When I create the loops for each of the sublists, I can easily do that within the 1 C# template but it becomes repetitive, long, and unruly because there's so much c# code where I'm looping the same session template for different entity picker sections. So, I tried using the "Render sub-template" code to simplify the template - I created new sub templates and inserted them in - it seemed to work at first, however, the template started outputting all "session" items into each item in the list.
I suspect that the subtemplate somehow loses the context of the item that it's in so it's outputting everything. Is there something special I need to know about using subtemplates with for each loops? Do I have to include params and, if so, how do I do that?
EDIT to include code sample:
Here is a small, simplified version of the code I'm working with:
#foreach(var Content in AsList(Data)) {
<h2>#Content.Title</h2>
<h3>Lead Sessions</h3>
<div class="lead-sessions text-green">
#foreach(var item in AsList(Content.LeadSessions as object)){
<h4>#item.LeadSessionTitle</h4>
<p>#item.LeadSessionText</p>
}
</div>
<h3>Next Sessions</h3>
<div class="next-sessions text-green">
#foreach(var nextitem in AsList(Content.NextSessions as object)){
<h4>#nextitem.LeadSessionTitle</h4>
<p>#nextitem.LeadSessionText</p>
}
</div>
}
I want to make a subtemplate so I don't have to repeat the same code for the sessions loop. How could I simplify this template to use a subtemplate for looping the sessions within the lead-sessions and next-sessions?
So based on the modified question, it's a bit like this
#foreach(var Content in AsList(Data)) {
<h2>#Content.Title</h2>
<h3>Lead Sessions</h3>
#RenderPage("_inner.cshtml", new { Items = Content.LeadSessions })
<h3>Next Sessions</h3>
#RenderPage("_inner.cshtml", new { Items = Content.NextSessions })
}
Second file _inner.cshtml
#{
var items = AsList(PageData["Items"]);
}
<div class="next-sessions text-green">
#foreach(var nextitem in items){
<h4>#nextitem.LeadSessionTitle</h4>
<p>#nextitem.LeadSessionText</p>
}
</div>
Yep, you can just use RenderPage without params, or pass in params like in the blog app:
#RenderPage("shared/_Category Filter.cshtml", new { MobileView = true, FilteredCategory = filteredCategory })
See https://github.com/2sic/app-blog/blob/master/_List.cshtml#L25
Then the template can retrieve the values like
#{
var filteredCategory = PageData["FilteredCategory"];
}
See https://github.com/2sic/app-blog/blob/master/shared/_Category%20Filter.cshtml#L6
You can pass around any amount of values/objects like this.
You can also create helpers - and then call those helpers. Like this
https://github.com/2sic/app-news/blob/master/shared/_Helpers.cshtml#L24-L33

Can't return data from Content Picker in Umbraco 7.6.4

I am currently trying to output data from the new Multinode Treepicker in Umbraco 7.6.4 here is my current setup and code:
Doctype
Content Node with 'Page' Doctype
Code to output the names of the selected nodes:
#{
IPublishedContent typedContentPicker = Model.Content.GetPropertyValue<IPublishedContent>("sections");
if (typedContentPicker != null)
{
<p>#typedContentPicker.Name</p>
}
}
This I took from the official Umbraco Documentation and adapted it to my project. This code is in a template with the 'page' doctype.
Currently the above code does not output anything to my page, I am expecting to see a list of nodes displayed on the page, can anyone see what the issue is or where I am going wrong?
Dumb moment, I was looking at the documentation for a content picker and not a multi-node tree picker!
Correct code is:
#{
var typedMultiNodeTreePicker = Model.Content.GetPropertyValue<IEnumerable<IPublishedContent>>("sections");
foreach (var item in typedMultiNodeTreePicker)
{
<p>#item.Name</p>
}
}

Issue with iterating using DescendantsOrSelf

I just recently upgraded Umbraco from 4.7.2 to 7.1.9 and now in the process of slowly converting all legacy macroscripts to partial view macros. I have come across a few issues when using DescendantsOrSelf to iterate through nodes.
I have a macro that generates the side menu for my site (intranet). With version 4 the macro worked as expected on the whole site displaying the appropriate menu on the homepage and different side menu's on the child pages.
After the upgrade the below condition:
var model = GetParentSideMenu(CurrentPage);
#if (CurrentPage.AncestorsOrSelf("umbSomePageType").Where("Visible").First().HasValue("PageName") && CurrentPage.AncestorsOrSelf("umbSomePageType").Where("Visible").First().Id != model.Id)
{ ... }
#functions
{
public dynamic GetParentSideMenu(dynamic model)
{
if (model.Level > 1)
{
do
{
if (model.umbSideMenuLinks.Count() > 0)
{
return model;
}
if (model.Level > 1) {
model = model.Up();
} else { break; }
} while (model.Up() != null);
return model;
}
else return model;
}
}
Generates the following error when rendered on the homepage:
System.InvalidOperationException {"Sequence contains no elements"}
Inner Exception is null
The understanding here is that the page being rendered is not "umbSomePageType" so this condition should be false and move on but instead it throws the above exception.
The macro works fine when rendered on a "umbSomePageType" page but as the user is allowed to have further sub pages of a another type under "umbSomePageType" I have to manually check the "DocumentTypeAlias" and make sure the other if statements checking for that type of sub page are not executed because I get the same error as above.
Another issue I am facing is this doesn't return an iterable collection when it used to before in v4:
#if (model.DescendantsOrSelf("umbSideMenuLinks").Where("Visible").Count() > 0)
{
foreach (var item in model.DescendantsOrSelf("umbSideMenuLinks").Where("Visible").First().Children)
{ ... }
.... }
The if condition returns true but the foreach is unable to get any elements to iterate through.
Any help here will be greatly appreciated.
Thank You.
I was able to find a solution to the first problem I specified above. The error was occurring in the "if" condition due to the "CurrentPage" being a dynamic object, "FirstOrDefault()" needs to be used instead of "First()".
The second issue still stands and to further detail that issue if you have the following directory structure:
Root Folder/Homepage
- Second Level Folder
-- SideMenuLinks (umbSideMenuLinks)
-- SomePage...
- SideMenuLinks (umbSideMenuLinks)
In the above case if I am on the "HomePage" and I want to render the "SideMenuLinks" pertaining to the homepage and I use "DecedantOrSelf" it will go from the root folder to the second level folder and to the "SideMenuLinks" instead of first checking it "Self" which is the behaviour I desire. This is something that worked in Umbraco v4 but in v7 it drills into the sub directories first.
Maybe if I reorder/sort the SideMenuLinks so they appear before the "Second Level Folder" ?
Haven't tried that yet.
UPDATE: So I just tried the sorting and if I sort the tree this way:
Root Folder/Homepage
- SideMenuLinks (umbSideMenuLinks)
- Second Level Folder
-- SideMenuLinks (umbSideMenuLinks)
-- SomePage...
It starts to work. In the future we will have to create the page structure this to make sure that the correct SideMenuLinks are hit.

Umbraco Razor Macro Parameter access with space

I am new to Umbraco. I am currently using Umbraco 7.0. I have created a Razor
macro with a parameter that will access property from home template page. In My Macro
due to space only first word of string displays and rest of the string is not
displayed. property
name is sliderHeading with value : My First Slide. Macro inserted in the template is
as follows :-
#Umbraco.RenderMacro("HomePageSlider", new {mediaId="1084",
sliderHeading=#Umbraco.Field("sliderHeading")})
// where sliderHeading is macro parameter.
Macro definition :-
#inherits umbraco.MacroEngines.DynamicNodeContext
#if (Parameter.mediaId != null)
{
var mediaFolder = Library.MediaById(Parameter.mediaId);
if (mediaFolder.Children.Any())
{
foreach (var mediaItem in mediaFolder.Children)
{
<div class="cycle-slide" style="background-
image:url(#mediaItem.umbracoFile)" data-cycle-title=#Parameter.sliderHeading
data-cycle-desc="Remember, you are not limited to image elements. You can display
other HTML too." data-cycle-link="#"></div>
}
}
}
So, in macro, parameter value is accessed by :- data-cycle-
title=#Parameter.sliderHeading.
Now my issue is that
if property value is :- "My First Slide". Then it will give wrong output "My" on page.
if property value is :- "My First Slide" with html space (&nbbsp;) in between Then it
will give right output "My First Slide" on page.
How should I access parameter in Macro, so that it will give right output.
Seems a bit simple but won't wrapping #Html.Raw or even #Raw round your code force the parameter to output with spaces?
Like:
data-cycle-title=#Raw(Parameter.sliderHeading)

Hide projection widget if query has no results

We are building a website with the Orchard CMS where we have campaign adds.
These adds are linked to pages through tags (not the orchard tag part).
Then we built a custom filter that take these tags into consideration when fetching the campaign adds and display them in a widget.
On some pages there are tags but no campaigns that match these tags. We would like to hide the widget at this point.
One solution is to edit the widget layer every time a new campaign is added. But I would like to have a more solid solution than this.
Summary:
We would like to hide the entire projection widget when the query returns an empty result.
// Madelene
Most of the markup in the widget is rendered by the Widget.Wrapper.cshtml template. What you can do is filter what this wrapper will render based on the content of the widget itself. This way if the widget doesn't render anything, you can decide to hide the title and the other zones. Here is the code doing it:
#using Orchard.ContentManagement;
#using Orchard.Widgets.Models;
#{
var widgetPart = ((IContent)Model.ContentItem).As<WidgetPart>();
var tag = Tag(Model, "article");
var childContent = Display(Model.Child);
}
#if (!String.IsNullOrEmpty(Convert.ToString(childContent))) {
#tag.StartElement
if ((widgetPart.RenderTitle && HasText(widgetPart.Title)) || Model.Header != null) {
<header>
#if ((widgetPart.RenderTitle && HasText(widgetPart.Title))) {
<h1>#widgetPart.Title</h1>
}
#Display(Model.Header)
</header>
}
#childContent
if (Model.Footer != null) {
<footer>
#Display(Model.Footer)
</footer>
}
#tag.EndElement
}
Just create a file named Widget.Wrapper.cshtml in your theme and paste this content. You can check what was the previous content if you want to understand how it's done.
you could override the Projection widget, you can then edit the code for that widget within the cshtml file. This is by far the easiest way.
or
You could create a custom filter that did a check for the dependency and returned no items if that dependency was not met (this is a harder way of doing it)