Umbraco get content from child pages - razor

Is there a way to render the content of x child pages onto their parent page?
Im using Umbraco 7 and im not very good with razor.
This is my attempt, found on an unanswered post in the umbraco forum:
(https://our.umbraco.org/forum/umbraco-7/using-umbraco-7/60936-Grid-on-CurrentPage-Children)
IPublishedContent currentPage = Umbraco.Content(CurrentPage.Id);
IEnumerable<IPublishedContent> children = currentPage.Children().Where(x => x.IsVisible());
foreach(var child in children){
#child.GetGridHtml("grid")
Doesnt work tough.
Error: Cannot implicitly convert type 'Umbraco.Core.Dynamics.DynamicNull' to 'Umbraco.Core.Models.IPublishedContent'.
Thanks for your support.
John

Umbraco.Content returns a dynamic. You need to get the IPublishedContent for the first line try:
IPublishedContent currentPage = Umbraco.TypedContent(CurrentPage.Id);
The problem then is x.IsVisible() doesn't work so you need to use:
x.GetPropertyValue<bool>("isVisible")

Related

How can I get the innerText of Dynamic Html tags using Puppeteer.js (node.js) in TripAdvisor?

How would I get all 10 comments located in this page with a loop or a Puppeteer function https://www.tripadvisor.com/Restaurant_Review-g294308-d3937445-Reviews-Maki-Quito_Pichincha_Province.html using innerText property?
The only solution I have come up with is getting the outerHTML of the whole container of comments and then try to substring to get all the comments, but that is not optimal and I think its a more difficult approach. Maybe there is an easier solution in Puppeteer I cant find?
I am doing this for educational purposes. The comments are in class="partial_entry" and I want to get the innerText of a Dynamic Html tag (I want all 10), like the ones you see here:
If I where to open the div that contains <div class="review-container" data-reviewid="606551292" data-collapsed="true" data-deferred="false"><!--trkN:3-->, I would get another with id="review_582693262". Getting to the point, If I get to a <div> that has class="partial_entry" this would be where my comment is located. I have tried a few things but I get null, because it is not found since the parent <div> for each comment has a unique id like id="review_xxxxxxxxx".
Its kind of difficult since the review id is autogenerated like id="review_xxxxxxxxx" and cant iterate with a loop copying the CSS path since I dont have a static parent .
Why not just select those elements which have partial_entry class? This works:
let comments = await page.evaluate(() =>
[...document.querySelectorAll(".partial_entry")].map(item => item.textContent)
);

Templatizer - How to render multiple times same template, Polymer 2.x

In Polymer 1.x I was used to write a templatize code like this:
renderTemplate(query, properties) {
let element = this.shadowRoot.querySelector(query);
this.templatize(element);
var instance = this.stamp(properties);
return instance;
}
which worked well. But in Polymer 2.x there is a new error message A <template> can only be templatized once. Well it doesn't make sense, because I have 1 template which I want to redistribute multiple times with different properties.
I am giving here an example of how is my code
I have #template1 and #template2
I want to render #template1 then #template2 then #template1.
In steps how I render templates:
1) templatize #template1
2) stamp properties
3) templatize #template2
4) stamp properties
5 a) templatize #template1 => ERROR
5 b) skip templatize and stamp properties => #template2 is rendered....
How am i able to make this possible? calling stamp() after rendering #template2 will result in another #template2 render. I want #template1, but I can't templatize #template1 because it has been already templatized. And stamp is always "binded" to last templatized element.
Am I doing something wrong? I do really hate Polymer because of it's bad documentation and hard to google something usefull
I found a workaround which is propably not the best solution but it works. I tried to search in source code for some solutions but there wasn't anything usefull except the one property called __templatizeOwner. This property is set to all templatized elements. Removing this property from an element is the way.
renderTemplate(query, properties) {
let element = this.shadowRoot.querySelector(query);
if(element.__templatizeOwner) {
element.__templatizeOwner = null;
}
this.templatize(element);
var instance = this.stamp(properties);
return instance;
}
I am not sure what side effects this might have (more memory usage or something) but this is the only way I was able to find out.

Displaying Umbraco Grid in Mega Menu

I want to display Umbraco Grid in Mega Menu, and I cannot use #CurrentPage.GetGridHtml("") in this scenario.
I need to get it using node variable: myNode.GetProperty("menuGrid")
What is the best way to do that?
You can use various ways of getting content from the grid. They are all described here: https://our.umbraco.org/documentation/getting-started/backoffice/property-editors/built-in-property-editors/grid-layout/render-grid-in-template.
In my opinion, the best way would be to create custom grid view / renderer and just use it here with proper method for retrieving content e.g.
#CurrentPage.GetGridHtml(Html, "yourGridPropertyAlias", "customgridview")
#CurrentPage.GetGridHtml(Html, "yourGridPropertyAlias", "/views/othercustomgridview.cshtml")
Marcin's suggestions were helpful with finding a solution.
Just in case somebody is looking for something similar I had my INode which hasn't got access to GetGridHtml. After convertion to typed content I regained access to that property
foreach (var country in countryNode.ChildrenAsList)
{
var myNode = Umbraco.TypedContent(country.Id);
var property = myNode.GetGridHtml("menuGrid");
}

How to use Archetype with Razor?

I can't believe I couldn't find examples online.
This is my simple Archetype.
This is what I tried:
<img src="#CurrentPage.ctaTopLeft.image" alt="#CurrentPage.ctaTopLeft.text">
but it gives this error:
'Archetype.Models.ArchetypeModel' does not contain a definition for 'image'
EDIT: This works:
<img src="#CurrentPage.GetPropertyValue("ctaTopLeft").Fieldsets[0].GetValue("image")" alt="#CurrentPage.GetPropertyValue("ctaTopLeft").Fieldsets[0].GetValue("text")">
Wondering if there is any shorter way of writing it?
Well, no - an Archetype property can have a complex, nested set of data quite often in collections which may also be nested. In fact, it's quite common to use a corresponding nested set of partial views just to render it out correctly if you have for example nested Archetype properties (it happens).
There are some tutorials/samples available for this sort of thing:
http://imulus.github.io/Archetype/ - Archetype home on Github
https://gist.github.com/kgiszewski/8863822 - this one is linked from the Archetype page above - gives some examples of usage with Razor/MVC.
There are also other packages designed to help you map Archetype properties to POCO as well - e.g. https://our.umbraco.org/projects/developer-tools/archetype-mapper/
I prefer the typed way of getting the properties.
var property = Model.Contet.GetPropertyValue<ArchetypeModel>("yourArchetypePropertyAlias");
if (property != null && property.Any()) {
foreach (var item in property) {
var imageId = item.GetValue<int>("yourImagePropertyAlias");
var text = item.GetValue<string>("yourTextPropertyAlias");
}
}

umbraco razor - getting fields from content

I have a 6 items of the same content type "news", in each item I have a field newsIntro. I want to put the fields in specific pages on another page so I need to target a specific field so it may be newsIntro on node 1702. I have tried a few things like
#1720.newsIntro
how do I target a specific field
Thanks
There are some great resources you should take a look at while you are learning Razor:
Umbraco Razor Feature Walkthrough - An eight part blog post series of many of the new Razor features in Umbraco 4.7 with examples.
Razor DynamicNode Cheat Sheet - A PDF of all the properties and methods available to the Razor DynamicNode object (that includes #Model).
Cultiv Razor Examples - An Umbraco website that you can download and open with WebMatrix or IIS and see various ways to access properties with Razor.
Razor snippets - A compilation of different snippets, examples, etc. from Our Umbraco.
But in answer to your question, to get a property of a specific node you have to get the actual DynamicNode object first, then use the property alias to access the property value. Example:
#{
//Get the node
dynamic node = Library.NodeById(1720);
// Display the property
#node.newsIntro
}
To access a property from the current page, you simply use Model:
#Model.newsIntro
or
#Model.bodyText
or
#Model.Name
First, get an IPublishedContent object from the TypedContent method and then use GetPropertyValue to retrieve the value of the field.
#{
int nodeId = 1720;
IPublishedContent contentNode = Umbraco.TypedContent(nodeId);
var newsIntro = contentNode.GetPropertyValue("newsIntro");
}
<p>#newsIntro</p>
With Umbraco 7 I used this code to get property from different pages:
#Umbraco.Content(1720).newsIntro
If the content item 1720 is a parent or ancestor of the page where you want to use the value, you can get it recursively like this:
#Umbraco.Field("newsIntro", recursive: true)
To get fields from content I have used this:
#{
var selection = Umbraco.TypedContent(contentId).Children()
.Where(x => x.IsVisible())
.OrderBy("CreateDate");
}
#foreach(var item in selection){
#item.GetPropertyValue("fieldName1")
#item.GetPropertyValue("fieldName2")
#item.GetPropertyValue("fieldName_N")
}