umbraco razor - getting fields from content - razor

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")
}

Related

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.

Umbraco get content from child pages

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")

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");
}
}

Orchard - Add an additional shape name (i.e. an alternate) for the main List shape

Introduce the Problem
I would like to profoundly modify the layout of the Orchard CMS Tags list.
Here is an example page with Shape Tracing enabled.
The only alternate that it suggests for the List shape is ~/Themes/TheThemeMachine/Views/List.cshtml, because the page is rendering the default List shape. I would like to have other alternates that are specific to the page.
After reading Orchard list customization, I have been able to implement the default List.cshtml in razor. What I would like to do, though, is to add another alternate, such as ~/Themes/TheThemeMachine/Views/Parts.Tags.List.cshtml instead of implementing the default List.cshtml template.
The problem seems to be that the page is rendering the generic List shape.
In contrast, the blog post list page is rendering a Parts_Blogs_BlogPost_List shape, which means that a ~/Themes/TheThemeMachine/Views/Parts.Blogs.BlogPost.List.cshtml is available.
Search and Research
All quotes below are from the Orchard list customization blog post, which explains how to add a list item alternate (whereas I would like to add a list alternate).
What we really want is an alternate template... aptly called Shape
Alternates... [so] enable Shape Tracing... and select a post in the list...
[you will see that] we already have some possible alternates.
My example page also has some possible alternates for the List Content. Cool.
we need to somehow get into list rendering... [t]he default is defined
in code... [which] can be override by a new [cshtml] template in our
theme.
Okay. That makes sense. We can override the list rendering.
As Shape Tracing can show, we can override the list rendering for a
blog by creating a Parts.Blog.BlogPost.List.cshtml template.
This works for alog but not for the blog Tag page (example page). You see, the blog displays a **Parts_Blogs_BlogPost_List shape and suggests an appropriate alternate but the blog tags page displays the default List shape with no alternates other than List.cshtml.
Blog Page with alternates galore
Blog Tags Page with one alternate List.cshtml
So, I created a List.cshtml not a Parts.Blog.BlogPost.List.cshtml template, and save it in my theme's Views directory. (One problem here is that, once we get it working, we will b overriding the default List rendering.)
Then I add the Razor code (copy and pasted from Bertrand's post) to override the default rendering for Lists. When I refresh the site, the browser renders a blank page. It isn't working. Here's the code:
This Does NOT Work in List.cshtml
#using Orchard.DisplayManagement.Shapes;
#{
var list = Model.ContentItems;
var items = list.Items;
var count = items.Count;
var listTag = Tag(list, "ul");
listTag.AddCssClass("content-items");
listTag.AddCssClass("blog-posts");
var index = 0;
}
#listTag.StartElement
#foreach (var item in items) {
var itemTag = Tag(item, "li");
if (index == 0) {
itemTag.AddCssClass("first");
}
else if (index == count - 1) {
itemTag.AddCssClass("last");
}
#itemTag.StartElement
#Display(item)
#itemTag.EndElement
++index;
}
#listTag.EndElement
As a trouble shooting step, I replace the List.cshtml with <p>Hello world.</p>. Orchard renders the markup as expected. So, something is incompatible between the Razor code from Bertrand's blog and the Tags List.
To find out what exactly is incompatible, I try Betrand's code one line at time to see where it breaks (yup, VS would be better than WM here). At each change, I restart WebMatrix and view the results. This is the minimal code that breaks it.
The Culprit
#using Orchard.DisplayManagement.Shapes;
#{
var list = Model.ContentItems;
var items = list.Items;
}
list.Items isn't appropriate here. So I comment it out again and run the <p>Hello World</p> version again. Also, Shape Tracing reveals that on my Tags/tagname page, the Content Zone is now rendering the List twice. Is that normal?
As another step, I replace Model.ContentItems just with Model. It works. It seems that, to override the List.cshtml template, we cannot use the ContentItems property of Model. Here is the new, working code:
This Does Work in List.cshtml
#using Orchard.DisplayManagement.Shapes;
#{
//var list = Model.ContentItems;
//var items = list.Items;
var items = Model.Items;
var count = items.Count;
//var listTag = Tag(list, "ul");
var listTag = Tag(Model, "ul");
listTag.AddCssClass("content-items");
listTag.AddCssClass("blog-posts");
var index = 0;
}
#listTag.StartElement
#foreach (var item in items) {
var itemTag = Tag(item, "li");
if (index == 0) {
itemTag.AddCssClass("first");
}
else if (index == count - 1) {
itemTag.AddCssClass("last");
}
#itemTag.StartElement
#Display(item)
#itemTag.EndElement
++index;
}
#listTag.EndElement
Onward through the article.
So far so good, we have effectively taken over the rendering of the
list, but the actual HTML [will] be... identical to what we had before
[except for] the implementation.
Okay. I'm following. We want to modify the rendering not just re-implement it.
Alternates are a collection of strings that describe additional shape
names for the current shape... in the Metadata.Alternates property of any shape.
Gotcha. Now, why doesn't the Tags/tagname page show an alternate other than just List.cshtml for the rendering of the List shape?
All we need to do is add to this list [of alternates]... [and make sure] to respect the lifecycle...
Great. Maybe we can we add another alternate for the List shape on the Tags/tagname page. But, doing that is different from what Betrand is explaining. While Betrand's blog post is excellent, it is explaining how to add an alternate for an item, whereas I would like to add an alternate for the list.
The List.cshtml template is where I would add an alternate for a List Item as follows:
ShapeMetadata metadata = item.Metadata;
string alternate = metadata.Type + "_" +
metadata.DisplayType + "__" +
item.ContentItem.ContentType +
"_First";
metadata.OnDisplaying(ctx => {
metadata.Alternates.Add(alternate);
});
So that...
[t]he list of alternates from Shape Tracing now contains a new item.
Where and how, though, would I add an alternate for the List shape? Bertrand has recommended to check out the Shape Table Providers blog post for this. The quotes below are from that post.
But what if you want to change another shape template for specific
pages, for example the main Content shape on the home page?
This looks like a fit, because my example is the main List shape on the tags page. To do this we...
... handle an event that is triggered every time a shape named "Content"
[in our case "List"] is about to be displayed. [It] is implemented in a shape table provider which is where you do all shape related site-wide operations.
Great! Here is my implementation for adding another template for the main List shape.
TheThemeMachine > ListShapeProvider.cs
namespace Themes.TheThemeMachine
{
using Orchard.DisplayManagement.Descriptors;
public class ListShapeProvider : IShapeTableProvider
{
public void Discover(ShapeTableBuilder builder)
{
System.Diagnostics.Debugger.Break(); // break not hit
builder.Describe("List").OnDisplaying(displaying => {
// do stuff to the shape
displaying.ShapeMetadata.Alternates.Add("Tags__List");
});
}
}
}
The above builds and runs but does not hit the breakpoint nor add an alternate for the List shape on the /tags page. So I looked into the Orchard.Azure.MediaServices module and its CloudVideoPlayerShape which implements IShapeTableProvider. Its breakpoint does get hit. How is my code for ListShapeProvider fundamentally different than the code for the CloudVideoPlayerShape?
Also, I installed the Orchard.Themes.CustomLayoutMachine.1.0.nupkg as suggested in Bertrand's blog post. It unfortunately no longer contains an implementation of IShapeTableProvider.
I have also looked at this szmyd post, which does not explain where to put the IShapeTableProvider code.
Further, I installed the Contoso theme from the Orchard Gallery. It works and builds after adding a reference to Microsoft.CSharp. It also includes an implementation of the IShapeTableProvider. Hooray! Comparing its ContentShapeProvider with my ListShapeProvider reveals a subtle but important difference:
Contoso.csproj
<ItemGroup>
<Compile Include="Code\ContentShapeProvider.cs" />
</ItemGroup>
My implementation didn't include the .cs file in the compilation, because my theme has neither a .csproj nor a App_Code folder. So, I recreated my theme with the following code generation:
orchard.exe
feature enable Orchard.CodeGeneration
codegen theme My.FirstTheme /CreateProject:true
theme enable My.FirstTheme
feature enable Orchard.DesignerTools
When adding the ListShapeProvider.cs file, Visual Studio automatically added a ItemGroup/Compile entry for the file, which included the code in compilation. Hooray!
These two posts will help.
Shape Shifting
List Customization
Here are steps of my own minimum solution.
Download and unzip Orchard.Source.1.8.zip.
Open "\Downloads\Orchard.Source.1.8\src\Orchard.sln" in Visual Studio.
Build the solution to create orchard.exe.
Generate a new theme with orchard.exe. Use CreateProject:true because you will need a csproj to include your .cs file.
orchard.exe
setup /SiteName:SITE /AdminUsername:ME /AdminPassword:PWD /DatabaseProvider:SqlCe
feature enable Orchard.CodeGeneration
codegen theme My.FirstTheme /CreateProject:true
theme enable My.FirstTheme
In VS, add a ListShapeProvier.cs file to the root (or any folder) in your theme.
Add the following code to ListShapeProvider.cs.
namespace My.FirstTheme
{
using Orchard.DisplayManagement.Descriptors;
public class ListShapeProvider : IShapeTableProvider
{
public void Discover(ShapeTableBuilder builder)
{
System.Diagnostics.Debugger.Break();
// implementation here
}
}
}
Build the solution.
Run Orchard.Web.
Visual Studio will break at System.Diagnostics.Debugger.Break(). If it doesn't, go to the Orchard Dashboard and make My.FirstTheme the Current Theme.
Now read Shape Shifting to implement public void Discover(ShapeTableBuilder builder).
This post should give you a full response: http://weblogs.asp.net/bleroy/archive/2011/05/23/orchard-list-customization-first-item-template.aspx

reading cookie value in play framewrok 2.2 scala template

I am trying to read a cookie value inside the play framework template (not inside a controller). I am trying the following which is not working:
# val cookieVal = request.cookies.get('PLAY_SESSION').value
Any suggestions to fix this will be greatly appreciated. The reason why I am trying this is to change how the page gets rendered based on a cookie value.
In templates you define vals as follows:
#defining(request.cookies.get('PLAY_SESSION').value) { theValue =>
<div>Hello #theValue</div>
}
I personally prefer to read the cookies in the controller and pass them to the template if needed.
suppose PLAY_SESSION stored "37f0983881ba00636868b42234a360d466fb944c-block_status=0&userId=159313257462171"
and you have to render on the basis of the value of block_status.
then in this case you can get its value by
session.get("block_status").get
to use it in template you have to import#implicit session:play.api.mvc.Session at your template.
now you can easily get values at template by #session.get("block_status").get
request.cookies.get("Org").get.value