Copied to clipboard

Flag this post as spam?

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


  • Saied 349 posts 674 karma points
    Aug 11, 2016 @ 16:27
    Saied
    1

    One template with conditional logic for multiple sites or vice versa?

    Hi,

    Initially I started off with two sites under one umbraco instance and I had one template that was used for both sites. I was using conditional logic to display certain things about the site or set certain things depending on the site. This was easy because I didn't have to modify 2 templates (1 for each site), but I did not like the fact that the views contained conditional logic.

    I then added a third site and decided to give each site its own template, for example, there is a HomeA.cshmtl, HomeB.cshtml, and HomeC.cshtml.

    This helped remove the conditional logic, but now I have to maintain 3 templates which are very identical.

    Is there a best approach to this and am I going about it the wrong way? Are there packages are tools to help with this?

    Thanks

  • Nicholas Westby 2054 posts 7104 karma points c-trib
    Aug 11, 2016 @ 16:36
    Nicholas Westby
    1

    I tend to build sites now using a widget-based approach. Pretty much every page is built using Archetype widgets. That means there is really only one template that renders those widgets.

    We have also used this technique for multiple sites that share that template. We were able to give each site a unique look by having the homepage node set a theme with a drop down property. Based on that theme, we attach some particular CSS classes and that gives us pretty much everything we need to make each site unique.

    If you aren't using widgets, you can still get some reusability by using different templates, but have those different templates use shared partial views. For example, you could have Slideshow.cshtml, then you could call Html.Partial from each homepage variant to render the slideshow.

    Another thing you could do is have each template use the same layout CSHTML files.

  • Saied 349 posts 674 karma points
    Aug 11, 2016 @ 16:46
    Saied
    0

    Hi Nicholas.

    Can you elaborate on widget based approach, maybe with an example?

    The 3 sites I am doing now are actually extremely similar. The theme is the same. Where it differs is some structure, but not a lot. Another part that differs is things like google analytics, branding, etc.

    Here are 2 of them so you can get an idea: www.sctflash.com and www.bullydog.com

  • Nicholas Westby 2054 posts 7104 karma points c-trib
    Aug 11, 2016 @ 16:53
    Nicholas Westby
    1

    Sure. Take a look at this homepage: https://www.allcarehealth.com/

    Currently, that page consists of this content (just a series of Archetype widgets in the "Main Content" property):

    Widgets

    The homepage, like every page in the site, is just rendered by looping through the widgets and rendering them:

    @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)
    
  • Saied 349 posts 674 karma points
    Aug 11, 2016 @ 17:07
    Saied
    0

    Nicholas,

    Very nice. I have a few questions.

    1. On my sites, not everything is a property, some things are hard-coded, would you recommend that every section be a property?
    2. If I have 2 sites and I want a video widget to appear at the top of the page on one and a sliding banner to appear on the top of the other, would I have to add an if else statement to the view?
    3. Why did you assign Model to page? Why not just use Model?
    4. What is page.Typical.MainContent?
    5. When you call GetView, does that return the widgets you created in the order they are specified under main content?
    6. Why did you keep Quad Actions and Disclaimer outside main content? If they were there, could you render those sections in a loop?
  • Nicholas Westby 2054 posts 7104 karma points c-trib
    Aug 11, 2016 @ 17:30
    Nicholas Westby
    0

    Here are some answers:

    1. I don't usually hardcode anything. Although, I don't know what you mean by "would you recommend that every section be a property". Note that almost all of the content on the page is rendered with a single property (i.e., "Main Content").
    2. No, you just use different widgets for each page. Archetype allows you to add any widget in any order (though, Archetype calls them "fieldsets").
    3. I probably assigned the Model variable to the page variable for clarity. For example, I find page.SEO.Title to be easier to read than Model.SEO.Title. It has no impact functionally, but it makes the code more readable.
    4. The page.Typical.MainContent property is of type IEnumerable<IWidget> (i.e., it is a collection of widgets for the page).
    5. The GetView function only operates on one widget, not on a collection of widgets. The outer for loop is what decides the order to render widgets in (it just renders in the order specified in the CMS). So, GetView returns a path to a CSHTML file that can render a widget.
    6. I keep quad actions and disclaimer outside of the main content because I do not consider them widgets. They exist on most every page, much like the header/footer. In other words, I don't find any value in making them composable elements.

    FYI, it may not be obvious, but there is a controller/action method that maps Umbraco content to a model that is then supplied to the view.

  • Saied 349 posts 674 karma points
    Aug 11, 2016 @ 18:30
    Saied
    0

    Hi Nicholas,

    What I meant by "would you recommend that every section be a property" is basically what you said in your answer. For every part of the page, would you consider making a fieldset out of it or would you hard code anything?

    Regarding number 2, let say you had another website that a Video widget under MainContent, but you only wanted to show the video widget on a certain site. If both sites shared a view, would you have to do some logic conditionally to determine which widget to show or would you create 2 home views for each site?

  • Saied 349 posts 674 karma points
    Aug 11, 2016 @ 18:48
    Saied
    0

    Nicholas,

    This is a continuation of my reply to you answers. I think I kind of got number 2, but just want to make sure. I keep confusing views with nodes.

    My 2 websites can share the same view and they can both have a home node, but on one website, under the node, I could set the video to hidden and on the other one, I could set the video to display and the slider to hidden. Or I could have a tab that is has a property for just that website? Is this the correct approach? or am I way off?

  • Nicholas Westby 2054 posts 7104 karma points c-trib
    Aug 11, 2016 @ 21:17
    Nicholas Westby
    0

    Not sure I follow. If you want one site without a video, simply do not add that widget to the "Main Content" property. All of the widgets are controlled by the content editor.

    Here's an example from the above website:

    Add Video Widget

    When I click any "+" button, I am presented with the dialog to add a widget (aka, fieldset). That would allow me to add a video widget to one of the homepages.

    If I added the video widget to a page I didn't want to add it to, I'd click the "X" button on the widget to delete it. Note that Archetype also allows you to change the order of widgets by dragging them (you do that by clicking the crosshair button an dragging).

  • Saied 349 posts 674 karma points
    Aug 11, 2016 @ 22:37
    Saied
    0

    Thanks Nicholas,

    I think I am over-complicating it. Since each website will have it's own home node, it makes sense now that I can turn the fieldsets on/off.

    A couple last questions I had were:

    1. All my sites share the same css, but if I wanted to, could I set this via a property as well too? Could I do this with the Layout?
    2. The markup for the sections my page contain very specific html and have to be in a very specific order for it to show up, so I am not sure I would render the views using the foreach although that might work. Is that pretty much how yours works meaning do your fieldsets contain html and what properties did you use for the html (I was assuming a Rich Text Editor)?
    3. Based on your example, it looks like it is good practice to have every node have a main content where you define the fieldsets that make up its content between the header and footer? Does this make sense?

    Thanks for the great help, Saied

  • Nicholas Westby 2054 posts 7104 karma points c-trib
    Aug 12, 2016 @ 00:31
    Nicholas Westby
    0
    1. If you had a drop down on your homepages that allow the user to select a theme, you can do all sorts of things based on that selection. For example, you could include different CSS files based on the chosen theme. You could also accomplish it with a different template or layout, but that might necessitate having different templates set for each page within each site, which could be a pain (though, I can think of one way that would make it a bit easier, and I can explain it if you want to go that route).
    2. In the example I gave, each widget has a CSHTML that allows it to render any arbitrary markup. Of course, that CSHTML file only controls that widget and not any sort of interaction between adjacent widgets. I tend to architect sites so that any widget can be next to any other widget, though that may not work very well if you don't start with a widget-based approach in mind. Not really sure what you are talking about with regard to the rich text editor. Perhaps the screenshot below that shows the expanded fieldset for the slideshow will help.
    3. Yep, that's pretty much how I do it. We also created this project so when a user creates a page of a particular document type (e.g., Homepage), we can automatically create the widgets they are likely to need for that type of page: https://our.umbraco.org/projects/backoffice-extensions/contenttemplates/ Note that while we use different document types to facilitate that default widget behavior, they all still use the same template.

    Slideshow

  • Saied 349 posts 674 karma points
    Aug 12, 2016 @ 00:48
    Saied
    0

    Oh Ok,

    I thought you actually stored the html for the fieldset in a Rich Text Editor, so is the markup for each fieldset stored in a partial view?

    When looping through the fieldsets and callingWidgetUtility.GetView(widget);, does that search the views section?

    What name does the view need to be? For example, for the slide show?

    So based on all this, I am assuming the values that you set such as the slideshow text are used in a partial view and then you render that view to the screen. Does your slide show partial view contain the logic to loop through each slide?

    Thanks again.

  • Nicholas Westby 2054 posts 7104 karma points c-trib
    Aug 12, 2016 @ 01:21
    Nicholas Westby
    0

    Yep, each widget has a CSHTML file that renders the widget in whatever way it decides is best. Actually, my newer approach is to just have each widget render itself, and I have most widgets inherit from a common base class that just generates an AngularJS directive that then decides what type of markup to use. However, if you aren't familiar with AngularJS, might be best to avoid that approach for now.

    Keep in mind that WidgetUtility.GetView is just a function I wrote, so it really could do anything you want it to do. In my case, it uses a bit of reflection magic to figure out which CSHTML Razor partial to use. However, you could do it by convention if you liked (e.g., you could name each CSHTML partial after the widget). Here's my implementation if you are curious:

    // Namespaces.
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using Widgets;
    using static System.Reflection.BindingFlags;
    using static System.Type;
    
    
    /// <summary>
    /// Helps manage widgets.
    /// </summary>
    public static class WidgetUtility
    {
    
        #region Properties
    
        /// <summary>
        /// Store the view paths by the widget type.
        /// </summary>
        private static Dictionary<Type, string> Paths { get; set; }
    
    
        /// <summary>
        /// A lock object to make the paths thread safe.
        /// </summary>
        private static object PathsLock { get; set; }
    
    
        /// <summary>
        /// Indicates whether or not the paths have been populated.
        /// </summary>
        private static bool PathsPopulated { get; set; }
    
        #endregion
    
    
        #region Constructors
    
        /// <summary>
        /// Static constructor.
        /// </summary>
        static WidgetUtility()
        {
            PathsLock = new object();
            PathsPopulated = false;
            Paths = new Dictionary<Type, string>();
        }
    
        #endregion
    
    
        #region Public Methods
    
        /// <summary>
        /// Gets the path to the view for the specified widget.
        /// </summary>
        /// <param name="widget">The widget to get the path for.</param>
        /// <returns>The view path, or null.</returns>
        public static string GetView(IWidget widget)
        {
            PopulateViews();
            var viewPath = default(string);
            return Paths.TryGetValue(widget.GetType(), out viewPath) ? viewPath : null;
        }
    
        #endregion
    
    
        #region Private Methods
    
        /// <summary>
        /// Populates the paths to the views for the widgets.
        /// </summary>
        /// <remarks>
        /// If the views have already been populated, this will return immediately.
        /// </remarks>
        private static void PopulateViews()
        {
    
            // Already done?
            if (PathsPopulated)
            {
                return;
            }
    
    
            // Get the paths.
            lock (PathsLock)
            {
    
                // Already done?
                if (PathsPopulated)
                {
                    return;
                }
    
    
                // Create instances of the types that implement WidgetView.
                var emptyParams = new ParameterModifier[] { };
                var target = typeof(WidgetView<>);
                var baseTarget = typeof(WidgetView);
                var instances = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x =>
                    {
                        try
                        {
                            return x.GetTypes();
                        }
                        catch (ReflectionTypeLoadException ex)
                        {
                            return ex.Types.Where(y => y != null);
                        }
                    });
    
                var widgetViews = instances
                    // that implement WidgetView...
                    .Where(x => baseTarget.IsAssignableFrom(x))
                    // and have a generic base type...
                    .Where(x => x.BaseType != null && x.BaseType.IsGenericType)
                    // and are not abstract...
                    .Where(x => !x.IsAbstract)
                    // and implement WidgetView<> (generic version)...
                    .Where(x => target.IsAssignableFrom(x.BaseType.GetGenericTypeDefinition()))
                    // and have a public default constructor.
                    .Where(x => x.GetConstructor(Instance | Public, null, EmptyTypes, emptyParams) != null)
                    // Create instance.
                    .Select(x => Activator.CreateInstance(x) as WidgetView)
                    .Where(x => x != null).ToArray();
    
    
                // Store paths for each widget type.
                foreach (var widgetView in widgetViews)
                {
                    var widgetType = widgetView.GetType().BaseType.GetGenericArguments().First();
                    Paths[widgetType] = widgetView.ViewPath;
                }
    
    
                // Done.
                PathsPopulated = true;
    
            }
    
        }
    
        #endregion
    
    }
    

    For my slideshow, I have a class that indicates the path to be used as the partial view when rendering the slideshow:

    /// <summary>
    /// Registers the view for the slideshow widget.
    /// </summary>
    public class SlideshowView : WidgetView<Slideshow>
    {
        public override string ViewPath => "~/Views/Partials/Widgets/Slideshow.cshtml";
    }
    

    Yes, the Slideshow.cshtml gets to decide how to render each slide. In my case, I'm just rendering it to JSON, then passing it to an AngularJS directive that then handles rendering each slide:

    @using AllCare.App.Extensions
    @using AllCare.App.Types
    @model AllCare.App.Widgets.Slideshow
    @{
        var source = Json.Encode(new
        {
            useSocialShare = Model.UseSocialShare,
            slides = Model.Slides.Select(x => x is Slide
                ? new
                {
                    type = "slide-image",
                    header = x.Header,
                    summary = x.Summary,
                    link = x.Link.GetAngularLink(),
                    image = x.Image.GetAnonObject(),
                    mobileImage = x.MobileImage != null ? x.MobileImage.GetAnonObject() : x.Image.GetAnonObject()
                } as object
                : new
                {
                    type = "slide-video",
                    header = x.Header,
                    summary = x.Summary,
                    link = x.Link.GetAngularLink(),
                    image = x.Image.GetAnonObject(),
                    mobileImage = x.MobileImage != null ? x.MobileImage.GetAnonObject() : x.Image.GetAnonObject(),
                    youtubeId = (x as VideoSlide).YouTubeID
                } as object
            ).ToArray()
        });
    }
    
    <json-source source="@source" html-fields="slides.summary">
        <slideshow slides="::ctrl.slides" use-social-share="::ctrl.useSocialShare"></slideshow>
    </json-source>
    

    If you view the source of any page, you'll actually see these AngularJS directives and a bunch of JSON. Not that you need to do that; it's just how I've done it in this case. You could simply loop over each slide using a for loop in razor.

  • Saied 349 posts 674 karma points
    Aug 19, 2016 @ 21:37
    Saied
    0

    Hi Nicholas,

    What is your WidgetView class?

    Thanks

  • Nicholas Westby 2054 posts 7104 karma points c-trib
    Aug 19, 2016 @ 22:02
    Nicholas Westby
    0

    Not a whole lot:

    /// <summary>
    /// A widget view defines the view to be used to render a widget.
    /// Implement this class to specify a view path for a widget.
    /// </summary>
    /// <typeparam name="T">
    /// The type of widget to get the view for.
    /// </typeparam>
    public abstract class WidgetView<T> : WidgetView
        where T : CommonWidget
    {
    }
    
    
    /// <summary>
    /// Do not implement this. This is a utility class that makes reflecting implementations of
    /// the generic WidgetView<> easier.
    /// </summary>
    public abstract class WidgetView
    {
    
        /// <summary>
        /// The path to the view for the widget.
        /// </summary>
        public abstract string ViewPath { get; }
    
    }
    
  • Saied 349 posts 674 karma points
    Aug 22, 2016 @ 13:30
    Saied
    0

    Hi Nicholas,

    I installed archetype and have successfully used it. I was thinking on how to set the view path for it. I was thinking of extending the ArcheTypeModel or ArcheTypeFieldSetModel and having a property called ViewPath for example. I was also thinking of actually adding a property (TextString) to each ArcheTypeModel I create. My only question with this is that would I be able to set this property on the whole ArchetypeModel or would it have to be set on each fieldset. So for exampl, if I create a slider, I want to set the ViewPath similar to how you set the alias for the ArcheType, not when you create the individual fieldsets.

    When I set the whole ArcheTypeModel, I am referring to the part where you set the Label, Alias, and Label Template. I was thinking if I could add my own property to this like view path or I could even use an existing one like the Alias?

    What do you think?

  • Nicholas Westby 2054 posts 7104 karma points c-trib
    Aug 22, 2016 @ 15:08
    Nicholas Westby
    0

    Not sure I follow exactly. However...

    If you are thinking of actually adding a ViewPath property to the Archetype in the back office editor for Archetype, I wouldn't recommend that. That's typically used for data entered by content editors, and this isn't a property you'd want them tinkering with.

    However, you could certainly create a base class, Widget, that all widgets inherit from. That base class could have a property or function that returns the view path. And widgets that implement it could override it if necessary.

    The base implementation of ViewPath could return a path based on the name of the current widget class (e.g., if a class is called Slideshow, it could return a path of ~/Views/Partials/Widgets/Slideshow.cshtml).

  • Saied 349 posts 674 karma points
    Aug 22, 2016 @ 15:15
    Saied
    0

    Hi Nicholas,

    Have you messed around with @Html.RenderArchetypePartial() and @Html.RenderArchetypePartials()?

    Do you know the difference between these?

    It apparently takes a View Path, so I was wondering if this would be a good option to?

    I actually tried extending ArcheTypeModel and ArcheTypeFieldSetModel, but for some reason it won't allow me.

    Thanks, Saied

  • Nicholas Westby 2054 posts 7104 karma points c-trib
    Aug 22, 2016 @ 15:41
    Nicholas Westby
    0

    I wouldn't recommend those unless you are fine with the convention it imposes. All it's really doing is figuring out a path and then, I suspect, calling Html.Partial for that path with the model. Should be easy enough to do that yourself.

  • Saied 349 posts 674 karma points
    Aug 22, 2016 @ 15:43
    Saied
    0

    Yeah, it seems so. I am trying a few different things

  • Saied 349 posts 674 karma points
    Aug 22, 2016 @ 17:36
    Saied
    0

    Nicholas,

    After looking at it, I agree with you. I don't like being constrained to the view. It would be better IMHO if you there wasn't a constraint, but I guess I could just use @Html.Partial in this case.

    With the approach you took, since you specify a ViewPath in another class, if someone asked you to change the ViewPath of a particular fieldset, wouldn't this require deploying some dll or the website?

    If my content managers are just responsible for setting properties, would @Html.Partial be OK? They would not be messing with the actual archetype.

    I think I am struggling with the views because of how the differ structurally and with the css. Essentially, I want to create an archetype that allows you to specify menu items and then I would render those menu items out. The problem arises when one website needs one view and one website needs another view. I would love to just pass the model and view to @Html.Partial and have it render the correct view for each website without having to do something like:

    if this website
       render this partial
    else
      render this one
    
  • Nicholas Westby 2054 posts 7104 karma points c-trib
    Aug 22, 2016 @ 18:57
    Nicholas Westby
    0

    When you say "menu items", is this for a primary navigation (e.g., that you'd normally see at the top of a website)? How different is the primary navigation on each site? Do you actually need to render something different with the markup?

    If the markup and structure of the data is very different, you can allow the content editor to choose between multiple fieldsets (e.g., "Menu Type 1" or "Menu Type 2").

    If it's just CSS that needs to differ, you can have a drop down to select a theme on each site's homepage, then adjust whatever you need to based on that theme selection.

    And if somebody asks you to change a view path, you would likely actually be creating an entirely new view. In that case, of course there'd be some extra files to deploy (perhaps with some DLL's recompiled). Normally, content editors are not even aware of the concept of view paths though.

  • Saied 349 posts 674 karma points
    Aug 22, 2016 @ 19:45
    Saied
    0

    Hi Nicholas,

    I think it would best if I gave you an example. One website has the following markup:

    <div id="responsive-top-nav-br">
        <div class="responsive-nav">
            <div class="close">
    
                <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
                     viewBox="0 0 94.9 94.9" enable-background="new 0 0 94.9 94.9" xml:space="preserve">
                <g>
                <path fill="#FFFFFF" d="M55.9,47.5L94.3,9.1c0.8-0.8,0.8-2.2,0-3l-5.5-5.5C88.4,0.2,87.9,0,87.3,0c-0.6,0-1.1,0.2-1.5,0.6L47.5,39
            L9.1,0.6c-0.8-0.8-2.2-0.8-3,0L0.6,6.1c-0.8,0.8-0.8,2.2,0,3L39,47.5L0.6,85.8c-0.8,0.8-0.8,2.2,0,3l5.5,5.5
            c0.4,0.4,0.9,0.6,1.5,0.6s1.1-0.2,1.5-0.6l38.4-38.4l38.4,38.4c0.4,0.4,0.9,0.6,1.5,0.6s1.1-0.2,1.5-0.6l5.5-5.5
            c0.8-0.8,0.8-2.2,0-3L55.9,47.5z" />
                    </g>
                </svg>
            </div><!-- close -->
            <nav class="menu">
                <ul>
                    <li><a href="/">HOME</a></li>
                    <li><a href="/products/search">PRODUCTS</a></li>
                    @if (Convert.ToBoolean(ConfigurationManager.AppSettings["ShowEcommerce"]))
                    {
                        <li>
    
                            <a href="/cart" class="cart-button">CART<div class="item-counter">0</div></a>
    
                        </li>
    
                    }
    
                    <li><a href="/where-to-buy">WHERE &nbsp; TO &nbsp; BUY</a></li>
                    <li><a href="/savings-calculator">SAVINGS CALCULATOR</a></li>
                    <li><a href="/support">SUPPORT</a></li>
                    <li><a href="/contact">CONTACT</a></li>
    
    
                    @if (isAuthenicated)
                    {
                        <li><a href="/user/account">ACCOUNT</a></li>
                        <li><a class="sign-out" href="#">SIGN OUT</a></li>
                    }
                    else
                    {
                        <li><a href="/user/product-registration">REGISTER PRODUCT</a></li>
                        <li><a href="/user/create-an-account">CREATE ACCOUNT</a></li>
                        <li><a href="/user/login">SIGN IN</a></li>
                    }
                    <li class="flag-container">
                        <a href="#google-translate-modal" id="mobileTrans" class="language-change english"></a>
    
                    </li>
                </ul>
            </nav>
        </div><!-- responsive nav -->
    </div>
    

    The other one has:

    <div id="responsive-top-nav">
        <div class="responsive-nav">
            <div class="close">
    
                <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
                     viewBox="0 0 94.9 94.9" enable-background="new 0 0 94.9 94.9" xml:space="preserve">
                <g>
                <path fill="#FFFFFF" d="M55.9,47.5L94.3,9.1c0.8-0.8,0.8-2.2,0-3l-5.5-5.5C88.4,0.2,87.9,0,87.3,0c-0.6,0-1.1,0.2-1.5,0.6L47.5,39
            L9.1,0.6c-0.8-0.8-2.2-0.8-3,0L0.6,6.1c-0.8,0.8-0.8,2.2,0,3L39,47.5L0.6,85.8c-0.8,0.8-0.8,2.2,0,3l5.5,5.5
            c0.4,0.4,0.9,0.6,1.5,0.6s1.1-0.2,1.5-0.6l38.4-38.4l38.4,38.4c0.4,0.4,0.9,0.6,1.5,0.6s1.1-0.2,1.5-0.6l5.5-5.5
            c0.8-0.8,0.8-2.2,0-3L55.9,47.5z" />
                    </g>
                </svg>
            </div><!-- close -->
            <nav class="menu">
                <ul>
                    <li><a href="/">HOME</a></li>
                    <li><a href="/products/search">PRODUCTS</a></li>
                    @if (Convert.ToBoolean(ConfigurationManager.AppSettings["ShowEcommerce"]))
                    {
                        <li>
    
                            <a href="/cart" class="cart-button">CART<div class="item-counter">0</div></a>
    
                        </li>
    
                    }
    
                    <li><a href="/where-to-buy">WHERE &nbsp; TO &nbsp; BUY</a></li>
                    <li><a href="/blog">BLOG</a></li>
                    <li><a href="/support">SUPPORT</a></li>
                    <li><a href="/contact">CONTACT</a></li>
    
    
                    @if (isAuthenicated)
                    {
                        <li><a href="/user/account">ACCOUNT</a></li>
                        <li><a class="sign-out" href="#">SIGN OUT</a></li>
                    }
                    else
                    {
                        <li><a href="/user/product-registration">REGISTER PRODUCT</a></li>
                        <li><a href="/user/create-an-account">CREATE ACCOUNT</a></li>
                        <li><a href="/user/login">SIGN IN</a></li>
                    }
                    <li class="flag-container">
                        <a href="#google-translate-modal" id="mobileTrans" class="language-change english"></a>
    
                    </li>
                </ul>
            </nav>
        </div><!-- responsive nav -->
    </div>
    

    So the differences is that one has an id of responsive-top-nav and the other has an id of responsive-top-nav-br and there are menu item differences.

    What I was doing before was I had 2 partials (one for each menu) and in my Master.cshtml, I was doing something like this:

    @if(website == "www.abc.com")
        @Html.Partial("menu1")
    else if(website == "www.def.com")
        @Html.Partial("menu2")
    

    I would really like to do something like

    @Html.Partial("menu")
    
  • Nicholas Westby 2054 posts 7104 karma points c-trib
    Aug 22, 2016 @ 21:24
    Nicholas Westby
    0

    In that case, you could simply have a drop down for which type of menu to show. And that drop down could be on the homepage. Inside of menu.cshtml, you'd then have a call to one of your two sub-partials based on the value of that drop down.

    That's assuming you keep your very much hardcoded menus, however. Ideally, content editors could construct these menus themselves by selecting various Archetype fieldsets for different types of menu items. In that case, you wouldn't need to make special menus for each site.

    I would also question why you need specific ID's of "responsive-top-nav" and "responsive-top-nav-br". Is that something that could be handled with a theme class (e.g., the body could have a theme class of "theme-primary" or "theme-secondary" and you could style based on that). If not, I'd wonder what these two different ID's actually do. If one enables some extra behavior, perhaps that behavior could be triggered by the content editor selecting a checkbox (e.g., a checkbox that says "Do That One Special Thing?").

  • Saied 349 posts 674 karma points
    Aug 23, 2016 @ 00:06
    Saied
    0

    Hi Nicholas,

    I get your point about the html structure of the menu. Unfortunately, it is not my design and I just have to fit it in. So if I have this right, what you are saying is to have a menu.cshtmland depending on the value of a dropdown (I don't necessarily have to use archetype in this case), load either menuA.cshtml or menuB.cshtml?

    I also thought about passing a class or id through a ViewBag that can come from a property so I wouldn't have to do any conditional logic in the view? What do you think about that possibility?

    This also raises another question. When to use archetype and when to not? Basically when is it overkill?

    Thanks again, Saied

  • Nicholas Westby 2054 posts 7104 karma points c-trib
    Aug 23, 2016 @ 04:45
    Nicholas Westby
    0

    I don't have an IDE in front of me, but I'm thinking you are talking about passing a view data dictionary to a partial view. That could work, though you could equally well just pass a model to that partial view (unless you need to pass something else, like an IPublishedContent).

    When to use archetype and when to not? Basically when is it overkill?

    That depends on a lot of factors. If you don't need it and you don't think you will need it, don't use it, I suppose.

  • Saied 349 posts 674 karma points
    Aug 23, 2016 @ 13:28
    Saied
    0

    Hi Nicholas,

    1. If you had a partial that only required one property, would you put it into a ViewBag or still pass in a model that contained that property?
    2. Do you know if it is possible to disable specify properties within an archetype or not an archetype, for example let's say I want to set a Google Analytics Code, but don't want content editors to mess with this?
    3. I did see something called ArcheTypeMapper that allows you to map your fieldset properties to your POCO classes. Have you used this?

    Thanks for all the great help, Saied

  • Nicholas Westby 2054 posts 7104 karma points c-trib
    Aug 23, 2016 @ 14:06
    Nicholas Westby
    0

    Could go either way. It is very much something used for the view, so it makes sense to pass it in a view-centric way.

    You can create a special property editor that is editable only once. Archetype doesn't have anything built in for this.

    I use Ditto and some Ditto Labs processors (not to mention a number of custom processors) to map Archetypes to POCOs: https://github.com/leekelleher/umbraco-ditto-labs/tree/32e797a056f31adc03eab0f2669061700fc2626c/src/Our.Umbraco.Ditto.Archetype/ComponentModel/Processors

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies