Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Nicole Polet 50 posts 202 karma points
    May 18, 2016 @ 23:33
    Nicole Polet
    0

    Render Content Node with Associated Template on Parent Page

    Disclaimer: complete noob to Umbraco here.

    What I'm trying to do is create a modular page where it is easy for content editors to add and remove sections.

    I have a parent doctype called "Modular page" and several different child doctypes which are variations of "content blocks" (the modular sections of the page), each having their own set of parameters and their own templates.

    I would like to have the "modular page" template list all of the child "content blocks" sequentially. So that all of the content blocks render in the modular page with their associated templates. (Hope this is making sense so far, I'm not super familiar with all the lingo yet).

    I've followed the tutorial here: https://our.umbraco.org/documentation/tutorials/creating-basic-site/articles-parent-and-article-items which does what I want it to do, except that it only pulls in specific parameters of the children. I want it to pull in the entire template that I've associated with the child.

    Has anyone else attempted to do something similar?

    Thanks in advance.

    Nicole

  • Alex Skrypnyk 6163 posts 24143 karma points MVP 8x admin c-trib
    May 19, 2016 @ 10:25
    Alex Skrypnyk
    3

    Hi Nicole,

    Welcome to our community.

    This is typical issue with Umbraco.

    We solve such issues with code like that:

    @foreach (var item in selection)
    {
        switch (item.DocumentTypeAlias)
        {
            case "pollPage":
                Html.RenderPartial("Trend Poll", item);
                break;
            case "counterAndText":
                Html.RenderPartial("Trend Counter", item);
                break;
            case "randomSlider":
                Html.RenderPartial("Trend Random Slider", item);
                break;
            case "subscriptionPage":
                Html.RenderPartial("Trend Subscription", item);
                break;
        }
    }
    

    So you get all your children nodes, and depending on docType render view.

    Ask if something.

    Cheers, Alex

  • Nicole Polet 50 posts 202 karma points
    May 19, 2016 @ 16:06
    Nicole Polet
    0

    Hi Alex, thanks so much for your response. While I was waiting for my post to be moderated, I did find a solution that works, but because I'm not very familiar with XSLT, Razor or Umbraco, I'm not sure if it's the best solution. Would you be able to have a look and let me know if this seems ok? Here's the code:

    <xsl:for-each select="$currentPage/child::*[@isDoc][not(self::modularPage)]">
    <xsl:value-of select="umbraco.library:RenderTemplate(@id,@template)" disable-output-escaping="yes"/>
    

    I added it as an XSLT file and created a macro for it, then rendered the macro on the parent page template.

    Thanks again!

  • Nicholas Westby 2054 posts 7103 karma points c-trib
    May 19, 2016 @ 18:38
    Nicholas Westby
    2

    Are you using an older version of Umbraco (e.g., 4.x)? If not, I would recommend avoiding XSLT at all costs. Here's an article I wrote that gives guidance on what old technologies to avoid: http://24days.in/umbraco/2015/umbraco-zeitgeist/ (see the bygone section: http://24days.in/umbraco/2015/umbraco-zeitgeist/#bygones)

    You are trying to create child node widgets, which I'd recommend against for Umbraco 7 (still a good option for Umbraco 6): http://24days.in/umbraco/2015/umbraco-zeitgeist/#child-node-widgets

    Instead, you can use Archetype: http://24days.in/umbraco/2015/umbraco-zeitgeist/#archetype

    Archetype allows you to create widgets: http://24days.in/umbraco/2015/umbraco-zeitgeist/#widgets

    You might also consider using the Umbraco Grid Layout for widgets: http://24days.in/umbraco/2015/umbraco-zeitgeist/#grid

  • Sotiris Filippidis 286 posts 1501 karma points
    May 19, 2016 @ 20:16
    Sotiris Filippidis
    1

    I faced the same issue in the past. I think I understand what you're trying to do - you're trying to construct a page by adding parts - e.g. rows, if you're into Bootstrap so that the editor can eventually have a page with any elements desired - a gallery there, content underneath, some bar chart under that etc.

    If I understand correctly, then the problem is that you can't actually have "templates" for those sections that are, essentially, nodes under your actual page, since you're never going to display them individually, but only as part of the "parent" page.

    What I did in a similar situation was to create macros for each section (some may argue with my choice, but I wanted to have the native support for caching and parameters that macros offer) and created a helper function that would iterate the page's children nodes and render a macro for each depending on the document type, something in the lines of the following code:

    public static IHtmlString RenderContentMacro(IPublishedContent item)
    {
                UmbracoHelper u = new UmbracoHelper(UmbracoContext.Current);
    
                switch (item.DocumentTypeAlias)
                {
                    case "sectionImageGallery":
                        return u.RenderMacro("SectionImageGallery");
    
                    case "sectionPortfolio":
                        return u.RenderMacro("SectionPortfolio");
    
                    case "sectionCounter":
                        return u.RenderMacro("SectionCounter");
                 }
    }
    

    And so forth.

    Then I would call it from my page's template, like this:

      foreach (IPublishedContent item in Model.Content.Children())
      {
                @SomeStaticHelperClass.RenderContentMacro(item)
    
      }
    

    Of course, this is a simplified example. But in general, that's what I'm doing to "construct" a page from sections.

  • Nicole Polet 50 posts 202 karma points
    May 19, 2016 @ 21:49
    Nicole Polet
    0

    Thanks Nicholas and Sotiris.

    Hmmm, this gives me a lot to think about. I had a long look at Archetype, and installed it (I'm using UaaS). But I did read that it's not really meant for page layouts and I feel like it could get complicated quite fast with what I'm trying to do. And also, to be honest, I'm having a hard time wrapping my head around how it works.

    Right now I'm thinking of using the xslt/macro way to add the child nodes to my page as sections (bootstrap-style rows), and then use Archetype to list modular components within those sections.

    @Nicholas- thank you for the articles, they were very helpful. I hear what you're saying about avoiding xslt, but do you think in this context it might be ok? I guess I'm having a hard time foreseeing what future problems could arise since I'm so unfamiliar with xslt, json, razor etc. (I really only know html, css and js).

  • Nicholas Westby 2054 posts 7103 karma points c-trib
    May 19, 2016 @ 22:05
    Nicholas Westby
    1

    I find Archetype to be perfectly suitable for layouts, especially now that I've implemented cross-Archetype fieldset dragging (allows you to change your mind on the layout without having to enter the content a second time): https://github.com/imulus/Archetype/issues/355

    Here's an example: https://nvisioncenters.com/

    That homepage is built with these Archetype widgets in the back office:

    Archetype Widgets

    I'd also recommend against the macro approach: http://24days.in/umbraco/2015/umbraco-zeitgeist/#macros

    Here's a bit of info on Razor: http://24days.in/umbraco/2015/umbraco-zeitgeist/#aspnet-mvc-razor

    However, suppose you do use macros, then I'd recommend Razor macros rather than XSLT macros. Razor is much more powerful, and will likely have more support in the future than XSLT. As an example, here's how you'd create a Razor version of that for loop that you created in XSLT:

    @foreach (var child in Model.Content.Children)
    {
        @Umbraco.RenderTemplate(child.Id, x.TemplateId)
    }
    
  • Sotiris Filippidis 286 posts 1501 karma points
    May 19, 2016 @ 23:22
    Sotiris Filippidis
    0

    TBH I wasn't aware that macros were discouraged, although it makes me a bit sad because it was always easier to configure caching etc. from the back-end. I'll take care to adapt my code, thanks Nicholas!

  • Nicholas Westby 2054 posts 7103 karma points c-trib
    May 19, 2016 @ 23:30
    Nicholas Westby
    0

    Avoiding macros is just my personal recommendation. I find very little need for them. If caching is the only reason to use them, perhaps @Html.CachedPartial would be a useful alternative.

    Rather than do something like use a macro in a rich text editor, something like Archetype to represent widgets seems more useful.

  • Sotiris Filippidis 286 posts 1501 karma points
    May 19, 2016 @ 23:37
    Sotiris Filippidis
    1

    My approach was (until now, at least) to have macros instead of partials, uncached when developing, and adjusting cache when the site went live, from the back-end. I don't use macros in the RTE, I find it very unconvenient (for me and for editors), so I'd go with a widget approach for that anyway. I'll give Archetype a try as soon as there's ground for that.

    It's just that macros (given that I started using them with Umbraco 4 and XSLT) seemed very convenient and I kept following that approach even with v7.

    You have a point, though as well as the article you linked - Macros can at some point introduce restrictions since they act as a wrapper for partial views so I agree it might be better to directly use partials.

  • Nicole Polet 50 posts 202 karma points
    Jul 15, 2016 @ 22:47
    Nicole Polet
    0

    @Nicholas Westby: I'm reviving this thread with hopes that you might be able to help me with Archetype?

    When I originally asked this question, I was in a giant time crunch to get our site launched and just had to go with a hasty solution involving macros.

    Now that our site is launched and we're not in such a dire time constraint, I think that Archetype might be the right solution for us long-term. I now have the time to actually learn and implement it.

    In one of your previous comments you mentioned that you had used Archetype for layouts successfully and used nvisioncenters.com as an example. I'm still having a really hard time wrapping my head around how it works though. I'm wondering if you can explain it to me like I'm 5?

    For example- I'm confused about how Archetype works with templates. Using your nvisioncenter example- would this page have its own unique doctype and template, or would it use a sort of generic "modular page" doctype/template that you would use for all your site's pages?

    I'm also confused about how you control the css classes on each Archetype widget. Does each Archetype widget have it's own associated template?

    I hope these questions made sense. Please let me know if not and I'll try to clarify.

    Thanks so much in advance for your help!

    Nicole

  • Nicholas Westby 2054 posts 7103 karma points c-trib
    Jul 16, 2016 @ 00:38
    Nicholas Westby
    100

    Here's another example of a site we just launched in which every page is composed entirely of Archetype widgets: https://www.allcarehealth.com/

    Every page renders using the same Typical.cshtml template file. I do have different document types, but the properties are virtually identical (I use differing document types for a different purpose that I won't explain here, as I don't want to confuse things further). Here are the contents of that file:

    @using AllCare.App.Pages
    @using AllCare.App.Utilities
    @inherits Umbraco.Web.Mvc.UmbracoViewPage<TypicalPage>
    @{
        Layout = "Wrapped.cshtml";
        var page = Model;
        var widgets = page.Typical.MainContent;
    }
    
    @section PageTitle{@page.SEO.Title}
    
    @foreach (var widget in widgets)
    {
        var view = WidgetUtility.GetView(widget);
        if (view != null)
        {
            @Html.Partial(view, widget)
        }
    }
    
    @Html.Partial("Quad Actions", page)
    
    @Html.Partial("Disclaimer", page)
    

    There is also a controller that populates the model that gets passed to this view.

    As you can see, all it really does is render a partial for each widget, passing the appropriate model for that widget to the partial.

    There are a bunch of ways you can associate partials with widgets (widgets, by the way, are synonymous with what Archetype calls fieldsets), but the method I chose for this site was to create classes that indicate the path to the partials for each widget (based on the Archetype fieldset alias of that widget). If you wanted to do something super simple, you could just use a switch statement like this:

    var path = default(string);
    switch (widgetAlias)
    {
        case "richText":
            path = "~/Views/Partials/Widgets/RichText.cshtml";
            break;
        case "banner":
            path = "~/Views/Partials/Widgets/Banner.cshtml";
            break;
    }
    

    Because each widget has its own CSHTML partial view, you can render any markup you like for each widget.

    Let me know if there is anything you'd like me to clarify further.

Please Sign in or register to post replies

Write your reply to:

Draft