How can i use a Macro to loop through the pages subpages of a certain type and render it's content using the page's template?
Right now I'm rendering the @box.bodyText, but I want to have different boxes using different templates.. Any other ideas for the same result is very much appreciated.
@{
var boxFolder = Model.BoxFolders.First();
var boxes = boxFolder.GetChildrenAsList.Where("Visible").OrderBy("SortOrder");
var i = 0;
if(boxes.Any())
{
<div class="row">
@foreach(var box in boxes)
{
i++;
<div class="span4">
<div class="box">
@box.bodyText
@* I WANT TO RENDER THE BOXES TEMPLATE
HERE INSTEAD OF BODY TEXT *@
</div>
</div>
if(i % 3 == 0 && box.Position() != boxes.Count())
{
@Html.Raw("</div><div class=\"row\">")
}
}
</div>
}
}
ie. this is off the top of my head to give direction more than 100% correct;
If (hasValue(@box.bodyText))
{ @Html.Partial("boxTemplate")}
else {whatever}
put the code ie @CurrentPage.bodyText (@Model.Content . .etc whichever you prefer) with required divs etc in the partial you create in the Partials forlder and you should be all sorted.
Thanks for your answer! I checked a tutorial on using it, looks about right! How would I use it in this context, that is, should i create a separate Macro called "RenderBoxes" or something? And how would I render this Macro in Razor style?:
Gary! You're getting to the "poodle's core" (it's a thing in Sweden at least..)
I can't use Html.Partial in my Macro! It says:
'System.Web.WebPages.Html.HtmlHelper' does not contain a definition for 'Partial' and no extension method 'Partial' accepting a first argument of type 'System.Web.WebPages.Html.HtmlHelper' could be found (are you missing a using directive or an assembly reference?)
And I can't figure out why not.. This might be my main issue actually :)
I sincerely hope that the poodles core is a good thing? I'm sure it is as we are all good people here.
As I hit the send button, the word macro came into my head- then I thought arrrgh!
Being honest, I avoid using macros, they just seem too complicated. I have only ever used Umbraco in an MVC way, and maybe the requirement has not arisen.
I would tend to use Partials for anything repeated with an if statement, if (output of dropdown = xxx, render a partial) then render a partial in the partial. In theory you couls use RenderSection if using MVC, but again I think the Macro would stop this from happening?
There was a thread about the difference between a partial macro and something else, will have a look and see if you cannot just use partials to see if this is like an updated way of achieving in the more MVC way.
Seems Barry Fogarty is of the same opinion, maybe it is in the planning of a page that creates the need for a macro, as opposed to my kind of thinking that they are not needed as I have partials.
The poodle's core is "the core of the problem" so in this case, a very good thing!
I'd LOVE to avoid the macros on my dev as well, but I think my mind has crashed in to a corner and I can't think of how to solve this in any other way.. It's quite simple really, I'd like to render a few boxes in the top of my page, if boxes have been added (All children inside the Box Folder are boxes :))
These boxes are nodes (potentially of various type), and they use different templates. I could do with these templates being Partials or MasterPages-templates (MVC Style, both being views..)
My approach would be - I will use words so it explains, then a bit of code for direction.
To put boxes at the top of a page, if they are children, then just foreach on them, if they are under a different node then go up the tree, come back down and find the document type that the box is found on. If you use the same document type under different node, then make the node you require the target node.
@foreach (var item = CurrentPage.Children.Take(3) (this will give you the first 3 children. or @CurrentPage,Children.OrderBy("UpdateDate").Take(3) will give you the latest 3 children, in order of update (ie last save and publish). ("CreateDate"), will ignore the recent save and publish and just show in order of date they were first created. Then {<div>@item.BodyText</div>} will give you the output on the page.
This can be inserted directly into the page, but put that in a partial, and just @Html.Partial("box") - with the above code in it will do exactly the same thing.
If they are somewhere else in the tree -
@{ var topNode = @CurrentPage.AncestorsOrSelf().Descendants("yourDocTypeAlias")}
@foreach (var item in TopeNode) {<div>@item.bodyText</div>}
Your view can look, in simple terms
Layout = "_layout.cshtml"
@Html.Partial("render3Boxes")
<div> your page goes here </div>
@Html.Partial("renderNext3Boxes")
if you use say, for renderNext3Boxes @CurrentPage.Children.OrderBy("UpdateDate").Skip(3).Take(3), then foreach on those you have the latest 3 at the top of the page, then the following three at the bottom.
Hope I've not been too simple, but rather than try to over complicate, start at the beginning and build upon that.
I use a partial for Navigation, a partial for my footer, but these live in the layout, so really the above page of repeated content is all partials, I can then use that anywhere, on any page with a simple call.
If you want to call the layout for each box individually to use again somewhere else.
If you just need the "whole banner" ie div with 3 boxes to be repeated, then put all of the code in the partial, ie make the Umbraco @CurrentPage.Ancestors. . . .then loop or whatever, then html, then next Umbraco @CurrentPage then html and so on until you have all the boxes you need. Then you just need to call the one partial.
I use the "individual" box way to help with responsive design, so all three across the top on desktop, then if I want to only show one on the mobule version, I do not need to separate. It will depend on the use, but this way can be flexible. I might want to show the other two boxes at the bottom of the page, so it allows me to do this. Or even in a sidebar. By putting the partial in a fixed width div to the view and making a div in the partial 100% width, you can render anywhere at the correct width.
Hope that helps, there are probably more, and better exaples, but all I do with repeated content is think Partial and not Macro.
Thanks for your quick and great response. Sorry for not getting back earlier! It seems friday night caught up with me and I had to leave the computer .. :) I'm pushing forward and I have now left all ugly Macro ideas in their graves. I've made a Partial View that foreaches the CurrentPage.BoxFolders.First().Children!
However, my next question (which may be answered in your previous post but I lost track someehere) is:
How can i take my box.Template to either: a. Pick what Partial View to show b. Show this template
And, how do i get my box data to go into that view?
I tried something like @Html.Partial(box.Template, box) but it says:
Compiler Error Message: CS1973: 'System.Web.Mvc.HtmlHelper' has no applicable method named 'Partial' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
But @Html.Partial("HtmlBox") works fine, only it's not very modular.. And doesn't contain my content :)
Best regards
Niclas
EDIT: It seems box.Template didn't really show anything, anytime, so i tried using box.DocumentTypeAlias, which gives the correct value ("HtmlBox", in this case), but i still can't show a Partial using the value.
They say if you give a man a fish, you feed him for one day - if you give him the tools to fish he can feed himself for a lifetime.
Very happy you found your solution and can now enjoy the MVC integration of Umbraco a little more.
Off to the beach now, will be fishing for spider crabs later, then can enjoy them tonight with friends and will be happy that helping people still brings a really good feeling, especially when they post code so others may learn from it too.
Render a node with it's template from Macro
Hi!
I'm building a page using MVC and Umbraco 6.0.3
How can i use a Macro to loop through the pages subpages of a certain type and render it's content using the page's template?
Right now I'm rendering the @box.bodyText, but I want to have different boxes using different templates.. Any other ideas for the same result is very much appreciated.
You need uComponents RenderTemplate :)
Rich
Hi Niclas
How about using a Partial?
ie. this is off the top of my head to give direction more than 100% correct;
If (hasValue(@box.bodyText))
{ @Html.Partial("boxTemplate")}
else {whatever}
put the code ie @CurrentPage.bodyText (@Model.Content . .etc whichever you prefer) with required divs etc in the partial you create in the Partials forlder and you should be all sorted.
Hope it helps
Gary
Hi Rich,
Thanks for your answer! I checked a tutorial on using it, looks about right! How would I use it in this context, that is, should i create a separate Macro called "RenderBoxes" or something? And how would I render this Macro in Razor style?:
Thanks!
Gary! You're getting to the "poodle's core" (it's a thing in Sweden at least..)
I can't use Html.Partial in my Macro! It says:
'System.Web.WebPages.Html.HtmlHelper' does not contain a definition for 'Partial' and no extension method 'Partial' accepting a first argument of type 'System.Web.WebPages.Html.HtmlHelper' could be found (are you missing a using directive or an assembly reference?)
And I can't figure out why not.. This might be my main issue actually :)
Niclas
I sincerely hope that the poodles core is a good thing? I'm sure it is as we are all good people here.
As I hit the send button, the word macro came into my head- then I thought arrrgh!
Being honest, I avoid using macros, they just seem too complicated. I have only ever used Umbraco in an MVC way, and maybe the requirement has not arisen.
I would tend to use Partials for anything repeated with an if statement, if (output of dropdown = xxx, render a partial) then render a partial in the partial. In theory you couls use RenderSection if using MVC, but again I think the Macro would stop this from happening?
There was a thread about the difference between a partial macro and something else, will have a look and see if you cannot just use partials to see if this is like an updated way of achieving in the more MVC way.
Gary
Hi
Found it http://our.umbraco.org/forum/core/general/38263-V6-What-are-the-differences-between-Partial-View-Macro-File-and-a-Razor-Macro
Seems Barry Fogarty is of the same opinion, maybe it is in the planning of a page that creates the need for a macro, as opposed to my kind of thinking that they are not needed as I have partials.
Regards
Gary
Seems like RenderTemplate won't work with MVC as it is currently.
Gary, thanks for sticking with me!
The poodle's core is "the core of the problem" so in this case, a very good thing!
I'd LOVE to avoid the macros on my dev as well, but I think my mind has crashed in to a corner and I can't think of how to solve this in any other way.. It's quite simple really, I'd like to render a few boxes in the top of my page, if boxes have been added (All children inside the Box Folder are boxes :))
These boxes are nodes (potentially of various type), and they use different templates. I could do with these templates being Partials or MasterPages-templates (MVC Style, both being views..)
Any ideas or pointers?
Hi Rich, thanks for helping out anyway! It sounded like a great way to do it, at first!
Hi
Would love to help if I can.
My approach would be - I will use words so it explains, then a bit of code for direction.
To put boxes at the top of a page, if they are children, then just foreach on them, if they are under a different node then go up the tree, come back down and find the document type that the box is found on. If you use the same document type under different node, then make the node you require the target node.
@foreach (var item = CurrentPage.Children.Take(3) (this will give you the first 3 children. or @CurrentPage,Children.OrderBy("UpdateDate").Take(3) will give you the latest 3 children, in order of update (ie last save and publish). ("CreateDate"), will ignore the recent save and publish and just show in order of date they were first created. Then {<div>@item.BodyText</div>} will give you the output on the page.
This can be inserted directly into the page, but put that in a partial, and just @Html.Partial("box") - with the above code in it will do exactly the same thing.
If they are somewhere else in the tree -
@{ var topNode = @CurrentPage.AncestorsOrSelf().Descendants("yourDocTypeAlias")}
@foreach (var item in TopeNode) {<div>@item.bodyText</div>}
Your view can look, in simple terms
Layout = "_layout.cshtml"
@Html.Partial("render3Boxes")
<div> your page goes here </div>
@Html.Partial("renderNext3Boxes")
if you use say, for renderNext3Boxes @CurrentPage.Children.OrderBy("UpdateDate").Skip(3).Take(3), then foreach on those you have the latest 3 at the top of the page, then the following three at the bottom.
Hope I've not been too simple, but rather than try to over complicate, start at the beginning and build upon that.
I use a partial for Navigation, a partial for my footer, but these live in the layout, so really the above page of repeated content is all partials, I can then use that anywhere, on any page with a simple call.
Hope it helps, any questions, please ask.
Gary
Hi
Now with your case
<div id= "wrapper">
<div box1>@Html.Partial("box1)</div>
<div box2>@Html.Partial("box2)</div>
<div box3>@Html.Partial("box3)</div>
</div wrapper>
If you want to call the layout for each box individually to use again somewhere else.
If you just need the "whole banner" ie div with 3 boxes to be repeated, then put all of the code in the partial, ie make the Umbraco @CurrentPage.Ancestors. . . .then loop or whatever, then html, then next Umbraco @CurrentPage then html and so on until you have all the boxes you need. Then you just need to call the one partial.
I use the "individual" box way to help with responsive design, so all three across the top on desktop, then if I want to only show one on the mobule version, I do not need to separate. It will depend on the use, but this way can be flexible. I might want to show the other two boxes at the bottom of the page, so it allows me to do this. Or even in a sidebar. By putting the partial in a fixed width div to the view and making a div in the partial 100% width, you can render anywhere at the correct width.
Hope that helps, there are probably more, and better exaples, but all I do with repeated content is think Partial and not Macro.
Best regards
Gary
Hi Gary!
Thanks for your quick and great response. Sorry for not getting back earlier! It seems friday night caught up with me and I had to leave the computer .. :)
I'm pushing forward and I have now left all ugly Macro ideas in their graves. I've made a Partial View that foreaches the CurrentPage.BoxFolders.First().Children!
However, my next question (which may be answered in your previous post but I lost track someehere) is:
How can i take my box.Template to either:
a. Pick what Partial View to show
b. Show this template
And, how do i get my box data to go into that view?
I tried something like @Html.Partial(box.Template, box) but it says:
Compiler Error Message: CS1973: 'System.Web.Mvc.HtmlHelper' has no applicable method named 'Partial' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
But @Html.Partial("HtmlBox") works fine, only it's not very modular.. And doesn't contain my content :)
Best regards
Niclas
EDIT: It seems box.Template didn't really show anything, anytime, so i tried using box.DocumentTypeAlias, which gives the correct value ("HtmlBox", in this case), but i still can't show a Partial using the value.
Hi guys!
Thanks to your help I've got it! For future reference, this is my current solution:
Page Template:
ThreeBoxGrid Partial:
HtmlBox Partial
Hi Niclas
Hope it was not too painful for you?
They say if you give a man a fish, you feed him for one day - if you give him the tools to fish he can feed himself for a lifetime.
Very happy you found your solution and can now enjoy the MVC integration of Umbraco a little more.
Off to the beach now, will be fishing for spider crabs later, then can enjoy them tonight with friends and will be happy that helping people still brings a really good feeling, especially when they post code so others may learn from it too.
Thank you Niclas, thank you Umbraco.
Gary
Hi gary!
Hope you had a good time spider crab fishing! I saw you're from Portugal, definitely a future travel destination of mine!
I hope you'll help me out some other time on the forums!
Regards
Niclas
is working on a reply...