I'm new to Razor and and putting together a multi-language site from various snippets and trying to learn Razor along the way. I created a partial that looks for items select from a multi-page picker and the lists out the properties. the result is a list of office locations I can use across various language sites without duplication content. However this solution is not ideal as for each site I still need to "pick" the items to appear on the page.
What I need is to find any nodes with a doctype of "location" and render it's properties. As this is multi-language the root is (-1) from wherever the search is happening. How would I do this in Razor??? The code I have to grab the properties is :
<h6>Visit the <a href="http://ebiquity-test.azurewebsites.net/@Html.Raw(panel.GetPropertyValue<string>("locationWebsite"))">local website</a></h6></li>
Asuuming it is and you are looking to select page2, subpage1 and page3 if rendering on any page in the HomeUS tree and page5 if in the HomeFR tree, then this should work:
var locationNodes = Model.AncestorOrSelf(1).Descendants("location");
If I've understood your structure wrong please let me know.
Thanks for you replies. I think my initial idea is too limiting. My structure is:
Content - EN (doctype globalSite) -- Hompege --- Page
- DE (doctype globalSite) -- Homepage --- Page
- LocalOffices -- UK (doctype localSite) --- Homepage ---- Page -- DE (doctype localSite) --- Homepage ---- Page
- Locations --Location
Basically my instance has 2 separate types of site that need to share information. Global (also broken down by language, EN, DE etc), and Local (which are essentially microsites for local office information. These are broken down by country UK, DE etc).
I though I would store address information in a separate folder so it can be access by a page within my global site (basically a list of all local head offices). However, I'm being a bit dim. It would make a lot more sense to store the information on the DocType "localSite" or have a location folder within each office. That way local offices can use:
var locationNodes =Model.AncestorOrSelf(1).Descendants("location");
and Global sites could use what???
var locationNodes =Model.AncestorOrSelf(-1).Descendants("location");
Would that work?
Once I've found the nodes is it just a case of rendering out the properties?
I have been thinking about this as I don't think it's quite as easy as perhaps it should be to find all descendants of all root nodes, this is what I have come up with so far:
@{
var allRootNodes = Umbraco.TypedContentAtRoot(); //returns collection of all root nodes
IEnumerable<IPublishedContent> allDesc = Enumerable.Empty<IPublishedContent>();
allDesc = allRootNodes.Aggregate(allDesc, (current, publishedContent) => current.Concat(publishedContent.Descendants("location")));
foreach (var publishedContent in allDesc.OrderBy(x=>x.Level)) //order by whatever you like
{
<p>@publishedContent.Name</p>
}
}
If anyone has any other ideas I would love to see them
I have just discovered a new and awesome method on the Umbraco helper called TypedContentAtXPath which solves this issue as you can execute any Xpath expression on the entire tree
e.g
var locationNodes = Umbraco.TypedContentAtXPath("//location");
What error do you get? Just to confirm, are you using v6.1 or above? Additionally are you trying to select all documents of the document type "Location", check the casing of the alias in Umbraco also as it is sensitive.
Compilation Error
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS1061: 'Umbraco.Web.UmbracoHelper' does not contain a definition for 'TypedContentAtXPath' and no extension method 'TypedContentAtXPath' accepting a first argument of type 'Umbraco.Web.UmbracoHelper' could be found (are you missing a using directive or an assembly reference?)
Source Error:
Line 7: @{
Line 8: @var locations = Model.Content.AncestorOrSelf().Descendants("Location");@
Line 9: var locations = Umbraco.TypedContentAtXPath("//Location");
Line 10: @var locations = Umbraco.TypedContentAtXPath("//Location");@
Line 11: }
I've upgraded Umbraco and can now render a list of locations.
One final question. I'm not used to targeting nodes in this way. How would I get property data from this node and not just @location.Name ? A description field (textString) for example and url?
Thanks so much for your help. With this bit of knowledge I can to automatically propogate my language dropdowns, location dropdowns and lists without relying on hard-coding, great.
Find nodes by doc type and list properties
Hi,
I'm new to Razor and and putting together a multi-language site from various snippets and trying to learn Razor along the way. I created a partial that looks for items select from a multi-page picker and the lists out the properties. the result is a list of office locations I can use across various language sites without duplication content. However this solution is not ideal as for each site I still need to "pick" the items to appear on the page.
What I need is to find any nodes with a doctype of "location" and render it's properties. As this is multi-language the root is (-1) from wherever the search is happening. How would I do this in Razor??? The code I have to grab the properties is :
@inherits Umbraco.Web.Mvc.UmbracoViewPage<IPublishedContent>
@{
Layout = null;
var nodeIds = Model.GetPropertyValue<string>("globalLocations").Split(',');
List<IPublishedContent> panels = new List<IPublishedContent>();
foreach(var nodeId in nodeIds)
{
if(!String.IsNullOrEmpty(nodeId))
{
var publishedContent = Umbraco.NiceUrl(Convert.ToInt32(nodeId));
if (!String.IsNullOrEmpty(publishedContent) && publishedContent!="#")
{
panels.Add(Umbraco.TypedContent(nodeId));
}
}
}
}
@if(panels.Count() > 0)
{
<ul class="large-block-grid-2 small-block-grid-2">
@foreach (var panel in panels)
{
if (panel != null)
{
<li>
@if(panel.HasValue("locationImage")){
var mediaItem = Umbraco.TypedMedia(panel.GetPropertyValue("locationImage"));
<img src="@mediaItem.GetPropertyValue("umbracoFile")" alt="@mediaItem.GetPropertyValue("Name")"/>
}
<h5 class="subheader">@Html.Raw(panel.GetPropertyValue<string>("locationCountry"))</h5>
<h6>@Html.Raw(panel.GetPropertyValue<string>("locationAddress"))</h6>
<h6>Visit the <a href="http://ebiquity-test.azurewebsites.net/@Html.Raw(panel.GetPropertyValue<string>("locationWebsite"))">local website</a></h6></li>
}
}
</ul>
}
@{
}
Thanks for any help offered :)
Soctt
Hi Scott,
I'm not 100% clear on your content structure, could you confirm if this example is correct:
HomeUS
Page1
Page2 (doctype location)
SubPage1 (doctype location)
Page3 (doctype location)
HomeFR
Page4
Page5 (doctype location)
Asuuming it is and you are looking to select page2, subpage1 and page3 if rendering on any page in the HomeUS tree and page5 if in the HomeFR tree, then this should work:
If I've understood your structure wrong please let me know.
Thanks,
Jeavon
Might be best to post an screenshot of your content tree.
Rich
Thanks for you replies. I think my initial idea is too limiting. My structure is:
Content
- EN (doctype globalSite)
-- Hompege
--- Page
- DE (doctype globalSite)
-- Homepage
--- Page
- LocalOffices
-- UK (doctype localSite)
--- Homepage
---- Page
-- DE (doctype localSite)
--- Homepage
---- Page
- Locations
--Location
Basically my instance has 2 separate types of site that need to share information. Global (also broken down by language, EN, DE etc), and Local (which are essentially microsites for local office information. These are broken down by country UK, DE etc).
I though I would store address information in a separate folder so it can be access by a page within my global site (basically a list of all local head offices). However, I'm being a bit dim. It would make a lot more sense to store the information on the DocType "localSite" or have a location folder within each office. That way local offices can use:
and Global sites could use what???
Would that work?
Once I've found the nodes is it just a case of rendering out the properties?
Hi Scott,
I have been thinking about this as I don't think it's quite as easy as perhaps it should be to find all descendants of all root nodes, this is what I have come up with so far:
If anyone has any other ideas I would love to see them
Jeavon
Hi Scott,
I have just discovered a new and awesome method on the Umbraco helper called TypedContentAtXPath which solves this issue as you can execute any Xpath expression on the entire tree
e.g
Thanks,
Jeavon
Thanks for the replies. I will investiagte and post result :)
Hi,
Thanks for the feedback. How exactly would I implement XPath. I've tried the following but get an error:
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
@{
var locations = Umbraco.TypedContentAtXPath("//Location");
}
@foreach (var location in locations) {
<li>
@location.Name
</li>
}
Hi Scott,
What error do you get? Just to confirm, are you using v6.1 or above? Additionally are you trying to select all documents of the document type "Location", check the casing of the alias in Umbraco also as it is sensitive.
Thanks,
Jeavon
Hi Jeavon,
I'm using 6.0.6. Is that an issue?
This is the error I'm getting:
Compilation Error Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS1061: 'Umbraco.Web.UmbracoHelper' does not contain a definition for 'TypedContentAtXPath' and no extension method 'TypedContentAtXPath' accepting a first argument of type 'Umbraco.Web.UmbracoHelper' could be found (are you missing a using directive or an assembly reference?)
Source Error:
Line 7: @{ Line 8: @var locations = Model.Content.AncestorOrSelf().Descendants("Location");@ Line 9: var locations = Umbraco.TypedContentAtXPath("//Location"); Line 10: @var locations = Umbraco.TypedContentAtXPath("//Location");@ Line 11: }
The code I'm using:
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage @{ Layout = "EBGlobalMaster.cshtml"; }
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage @{ @var locations = Model.Content.AncestorOrSelf().Descendants("Location");@ var locations = Umbraco.TypedContentAtXPath("//Location"); @var locations = Umbraco.TypedContentAtXPath("//Location");@ }
Hi Scott,
Yes indeed, to use the TypedContentAtXPath method you will need to upgrade to the latest v6.1.3 as it was added in v6.1.0.
Thanks,
Jeavon
Oh :)
Looks like I'm due for an update this afternoon.
Thanks for the reply.
Scott
I've upgraded Umbraco and can now render a list of locations.
One final question. I'm not used to targeting nodes in this way. How would I get property data from this node and not just @location.Name ? A description field (textString) for example and url?
Thanks so much for your help. With this bit of knowledge I can to automatically propogate my language dropdowns, location dropdowns and lists without relying on hard-coding, great.
Scott
Hi Scott,
Now that I can see you full code, will I try to help the best I can.
But if you get the name, bye this @location.Name, you should be able to something like.
@location.ProppertyAlias to get custom filed. If you have a field with a proppery alias of description, this code should work for you.
And the exaple with the url you can do it like this;
I hope this helps you
/Dennis
Brilliant, thanks for your help Dennis
Hi Scott, to be able to request properties in the way that Dennis has shown you will need to use ContentAtXPath method instead of TypedContentAtXPath as the example is using dynamics. To use TypedContent you would need to do something like @item.GetPropertyValue("Description") Take at look at this documentation for examples of both dynamic and typed access http://our.umbraco.org/documentation/Using-Umbraco/Backoffice-Overview/Property-Editors/Built-in-Property-Editors/Textbox
Jeavon
is working on a reply...