smithsson68@gmail.com
Apr 7, 2011
  6946
(1 votes)

Providing a custom view for your Visitor Group criteria

In this blog post, Magnus Paulsson shows us a nice example of creating a criterion for the EPiServer Visitor Group framework and making the UI richer with the use of DoJo and MVC controllers. In this post I would like to show you how you can provide your own custom view for a criterion to plug-in to the Visitor Group Admin.

The Visitor Group Admin user interface is MVC 2.0 based and therefore uses convention over configuration. What that means is that you don’t use web.config or code based attributes to register a Visitor Group Admin criterion view like you would for other types of EPiServer CMS view plug-ins. Where the view is placed in the site’s structure and what it is called are the conventions that make it work.

So for example, to provide a custom view for Magnus’ example, you would create a typed MVC Partial View, the View Data class is the Visitor Group model, in this case:

ACME.Personalization.VisitorGroups.Criteria.RoleModel

The view should be given the same name as the model:

RoleModel.ascx
image

and it should be placed in the following folder structure in the site:

image

Now when an instance of the criterion is added to a Visitor Group in Visitor Group Admin, the custom view will be shown instead of the default one.

Of course you may use any HTML you like in your custom view but the EPiServer Visitor Group framework adds some extension methods to the System.Web.Mvc.HtmlHelper instance that can be used. The extension methods help you render the edit control html for your model’s properties leaving you free to concentrate more on the overall layout.

In Magnus’ example his model has 2 properties:

[DojoWidget(
SelectionFactoryType = typeof(EnumSelectionFactory),
LabelTranslationKey = "/shell/cms/visitorgroups/criteria/role/comparecondition",
AdditionalOptions = "{ selectOnClick: true }"),
Required]
public RoleCompareCondition Condition { get; set; }

[DojoWidget(
LabelTranslationKey = "/shell/cms/visitorgroups/criteria/role/rolename",
AdditionalOptions = "{ selectOnClick: true }"),
Required]
public string RoleName { get; set; }

The Condition property is decorated with the DojoWidget attribute and the SelectionFactoryType property is set. In this case the EPiServer Visitor Group framework will render a dijit.form.FilteringSelect control by default. In your custom view you can render the default edit control for the property by calling one of the DojoEditorFor extension methods provided:

<%= Html.DojoEditorFor(model => model.Condition)%>

There are 5 overloads of the DojoEditorFor method available:

/// <summary>
/// Creates Dojo editor.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <param name="html">The HTML helper.</param>
/// <param name="p">The property.</param>
/// <param name="htmlAttributes">Additional html attributes</param>
/// <param name="label">The label text.</param>
/// <param name="labelCssClass">Css class for the label</param>
/// <param name="labelPosition">The position of the label relative to the editor control</param>
/// <returns>The rendered HTML markup</returns>
public static MvcHtmlString DojoEditorFor<TModel>(this HtmlHelper<TModel> html, PropertyInfo propertyInfo, object htmlAttributes, string label, string labelCssClass, LabelPosition labelPosition)

/// <summary>
/// Creates Dojo editor.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="html">The HTML helper.</param>
/// <param name="expression">The property expression.</param>
/// <param name="htmlAttributes">Additional html attributes</param>
/// <param name="label">The label text.</param>
/// <param name="labelCssClass">Css class for the label</param>
/// <param name="labelPosition">The position of the label relative to the editor control</param>
/// <returns>The rendered HTML markup</returns>
public static MvcHtmlString DojoEditorFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes, string label, string labelCssClass, LabelPosition labelPosition)

/// <summary>
/// Creates Dojo editor.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="html">The HTML helper.</param>
/// <param name="expression">The property expression.</param>
/// <param name="htmlAttributes">Additional html attributes</param>
/// <param name="label">The label text.</param>
/// <param name="labelCssClass">Css class for the label</param>
/// <returns>The rendered HTML markup</returns>
public static MvcHtmlString DojoEditorFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes, string label, string labelCssClass)

/// <summary>
/// Creates Dojo editor.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="html">The HTML helper.</param>
/// <param name="expression">The property expression.</param>
/// <param name="htmlAttributes">Additional html attributes</param>
/// <returns>The rendered HTML markup</returns>
public static MvcHtmlString DojoEditorFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes)

/// <summary>
/// Creates Dojo editor.
/// </summary>
/// <typeparam name="TModel">The type of the model.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="html">The HTML helper.</param>
/// <param name="expression">The property expression.</param>
/// <returns>The rendered HTML markup</returns>
public static MvcHtmlString DojoEditorFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)



 

The custom view for Magnus’ Visitor Group criterion model could look something like this:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ACME.Personalization.VisitorGroups.Criteria.RoleModel>" %>
<%@ Import Namespace="EPiServer.Personalization.VisitorGroups" %>
<div class="somefancyclassthatmakesthislookreallycool">
    <div>
        <%= Html.DojoEditorFor(model => model.Condition)%>
    </div>
    <div>
        <%= Html.DojoEditorFor(model => model.RoleName)%>
    </div>
</div>

Of course you don’t need to use the DojoEditorFor methods. You can ride roughshod over the model’s user interface demands and render the edit user interface however you like. However, there is a big chance of problems here as the edit controls you use must be compatible with the dijit controls the Visitor Group framework is expecting for the property. For example, given a model class like this:

public class TestCriterionModel : CriterionModelBase
{
    public string SomeStringValue { get; set; }
    public int SomeIntValue { get; set; }
    public bool SomeBoolValue { get; set; }

    public override ICriterionModel Copy()
    {
        return base.ShallowCopy();
    }
}

you could define your view using your own HTML for the edit controls as follows;

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<EPiServer.TestCriterionModel>" %>
<div>
    <div>
        <input type="text" id="SomeStringValue" />
    </div>
    <div>
        <input type="text" id="SomeIntValue" />
    </div>
    <div>
        <input type="text" id="SomeBoolValue" />
    </div>
</div>

and it works quite happily:

image

However, as you can see the dijit styles used by the Visitor Group framework have been applied to the controls and they no longer look like plain <input> controls any more. So the point here is to use the DojoEditorFor extension methods where possible to render the edit controls and if some reason you don’t want to then expect to get into some javascript to fight against what the Visitor Group framework does.

By using a combination of custom views and the Dojo Javascript Framework you can really personalize the Visitor Group Admin user inteface.

Happy customizing!

Apr 07, 2011

Comments

Magnus Rahl
Magnus Rahl Apr 8, 2011 09:00 AM

Nice! Have to find time to try it out :)

May 22, 2017 10:39 PM

Please login to comment.
Latest blogs
Opti ID overview

Opti ID allows you to log in once and switch between Optimizely products using Okta, Entra ID, or a local account. You can also manage all your use...

K Khan | Jul 26, 2024

Getting Started with Optimizely SaaS using Next.js Starter App - Extend a component - Part 3

This is the final part of our Optimizely SaaS CMS proof-of-concept (POC) blog series. In this post, we'll dive into extending a component within th...

Raghavendra Murthy | Jul 23, 2024 | Syndicated blog

Optimizely Graph – Faceting with Geta Categories

Overview As Optimizely Graph (and Content Cloud SaaS) makes its global debut, it is known that there are going to be some bugs and quirks. One of t...

Eric Markson | Jul 22, 2024 | Syndicated blog

Integration Bynder (DAM) with Optimizely

Bynder is a comprehensive digital asset management (DAM) platform that enables businesses to efficiently manage, store, organize, and share their...

Sanjay Kumar | Jul 22, 2024