Defining widget properties in MVC

When developing widgets for MVC sites, you can define properties that allow content editors to adjust the widget content or behavior directly in the Kentico administration interface. Users interact with widget properties through the widget configuration dialog or inline editors, which you need to implement.

Use the following process to develop properties for a widget:

  1. Create a model class that defines the widget properties
  2. Handle the properties in the widget controller
  3. Allow content editors to modify the properties:

To see a scenario with full code samples which will guide you through the process of developing a simple widget with a property, visit Example - Developing a widget in MVC.

MVC Areas

Widgets are designed as global components. Adding related files, such as property model classes or inline editor files, into MVC Areas is not supported and may lead to unexpected behavior.

Creating property models

The properties of a widget must be defined within a model class that implements the IWidgetProperties interface (available in the Kentico.PageBuilder.Web.Mvc namespace).

Specify each widget property by creating a corresponding property in the model class. You can also set default values for the properties.

Example
public class CustomWidgetProperties : IWidgetProperties
{
    // Defines a property and sets its default value
    public int Number { get; set; } = 22;
}

You can use the Newtonsoft.Json.JsonIgnore attribute to exclude dynamically computed widget properties from database serialization.

It is recommended to store widget property models in the ~/Models/Widgets/<widget name> folder.

Handling properties in widget controllers

To work with the properties in your widget controllers, the controller class must inherit from the generic WidgetController<T> base class, with the appropriate property model class as the generic type parameter.

public class CustomWidgetController : WidgetController<CustomWidgetProperties>

Retrieve the properties as a strongly typed object by calling the GetProperties method (provided by the base class). The method returns an object of the specified property model class. The object's property values are loaded from the current configuration of the processed widget.

// Gets the value of a widget property (e.g. within the widget controller's Index action)
CustomWidgetProperties properties = GetProperties();
int propertyValue = properties.Number;

You can then adjust the code of your controller based on the values of individual widget properties, or pass them to the widget's view using the appropriate view model.

Model separation

Do not directly pass the property model to your widget views. Passing data to views is the responsibility of the widget's view model, and we strongly recommend keeping the models separate.

Defining the configuration dialog

The configuration dialog is a simple way to allow content editors to set values for widget properties. In the properties model class, you need to define editing form components for widget properties which you want to make editable in the configuration dialog. You can use the system's default form components or develop custom form components.

  1. Edit the widget's properties class in your MVC project.
  2. Define the visual interface of the configuration dialog:

    • Decorate the appropriate properties using the EditingComponent attribute (available in the Kentico.Forms.Web.Mvc namespace).

    • The attribute assigns and configures a form component, which is used as the input element for the given property in the configuration dialog.
    • For more information, see Defining form component properties.

    Example - Setting an editing component
    [EditingComponent(TextInputComponent.IDENTIFIER, Order = 0, Label = "Text")]
    public string Text { get; set; }

Users can now click the Configure () icon when working with widgets in the Kentico administration interface. This opens the widget properties dialog, and the configured property values affect the appearance and functionality of the widget on the live site.

Implementing inline property editors

Inline editors are interactive parts of a widget's output that allow content editors to configure the widget's properties. For example, inline editors can range from basic value inputs to more advanced options, such as file uploaders or text areas with rich formatting options.

The editors are visible only in the Kentico administration interface when working with pages that contain editable areas. However, the configured properties then affect the appearance of the given widget on the live site.

Note: Each inline editor manages only a single widget property. For widgets that have multiple properties, you can add multiple inline editors into the widget's output.

To create an inline editor for a property and integrate it into your widgets:

  1. Add an editor view model class to your MVC project.
    • The model class should contain at least two properties – the name and value of the widget property managed by the editor.
    • We recommend storing the view models of inline editors in a designated folder, for example: ~/Models/InlineEditors/<editor name>/

      public class CustomEditorModel
      {
      	public string PropertyName { get; set; }
      	...
      }
  2. Create a partial view that defines the inline editor's interface.
    • Make the partial view use the view model that you created for the editor.
    • The view code must encapsulate inner HTML elements using the Kentico().BeginInlineEditor() helper method. Specify the following parameters for the method:

      • A unique identifier of the inline editor.
      • The name of the widget property managed by the editor.
      @using Kentico.PageBuilder.Web.Mvc
      @using Kentico.Web.Mvc
      
      @model CustomEditorModel
      
      @using (Html.Kentico().BeginInlineEditor("custom-editor", Model.PropertyName))
      {
      	...
      }
    • We recommend storing the partial views of inline editors in a designated folder, for example: ~/Views/Shared/InlineEditors/
  3. Create a JavaScript file containing a self invoking function that registers the property editor. Every widget property editor must be registered using client-side code.
    • To register the property editor, call the window.kentico.pageBuilder.registerInlineEditor function.

      (function () {
        // Registers the 'custom-editor' inline property editor within the page builder scripts
        window.kentico.pageBuilder.registerInlineEditor("custom-editor", {
          init: function (options) {
      		var editor = options.editor;
              ...
          }
        });
      })();

      Specify the following parameters when calling the registerInlineEditor function:

      • The identifier of the property editor, i.e. the first parameter set for the BeginInlineEditor helper method in the HTML code of the editor's partial view.
      • An anonymous object with an init property function that is executed whenever the given property editor is loaded. Use this function to run custom JavaScript that modifies the widget's content or behavior based on the property value. The options parameter is an object that wraps the following properties:
        • editor – the DOM element encapsulating the editor
        • propertyName – the name of the related widget property
        • propertyValue – the value of the related widget property
        • localizationService –  the localization service

      Executing scripts on inline editor events

      If you need to execute custom scripts on certain events, you can use additional property functions of the anonymous object defined when registering the inline editor.

      // Mandatory:
      init: function (options) { ... },
      // Optional:
      destroy: function (options) { ... },   // Executed when a user deletes a widget containing the inline editor
      dragStart: function (options) { ... }, // Executed when a user starts to drag a widget with the inline editor
      drop: function (options) { ... }       // Executed when a user successfully drops a widget with the inline editor

      Only the editor property is available via the options parameter in the destroy, dragStart, and drop property functions.

    • To notify the widget about changes in the property value, dispatch a custom event named updateProperty (within the init function that you registered for the editor).

      // Creates a custom event that notifies the widget about a change in the value of a property
      var event = new CustomEvent("updateProperty", {
          detail: {
              value: "newValue",
              name: propertyName
          }
      });
      editor.dispatchEvent(event);

      The updateProperty event's data must contain the detail property, with the following values:

      • value – the new value of the widget property.
      • name – the name of the related widget property.
      • (Optional) refreshMarkup – bool value that determines whether the event automatically triggers a refresh of the widget's entire markup from the server. True by default.

      Inline editor scripts on multilingual sites

      When using inline editors on a site with a multilingual user interface, you need to display and submit values (e.g. dates and numbers) in the correct format for the respective culture. Use the Date and Number objects to store and handle any date and number values within your inline editor scripts.

  4. Prepare any additional assets required by the editor, such as further JavaScript files, CSS stylesheets, images, etc.
  5. Edit the partial views of the widgets where you want to integrate the editor:
    1. Evaluate Context.Kentico().PageBuilder().EditMode to determine whether the widget is being displayed in edit mode (in the Kentico administration interface).
    2. Render the editor's partial view in the appropriate location. Use the editor's view model to pass the name and current value of the related widget property.

      @using Kentico.PageBuilder.Web.Mvc
      @using Kentico.Web.Mvc
      
      @if (Context.Kentico().PageBuilder().EditMode)
      {
          Html.RenderPartial("InlineEditors/CustomEditor", new CustomEditorModel
          {
      		@* Use the nameof() operator to get the name of the widget property from the widget properties model *@
              PropertyName = nameof(CustomWidgetProperties.Number), 
              PropertyValue = Model.Number
          });
      }

The modified widgets now display your inline editor when working with page content in the Kentico administration interface. The appearance of widgets on the live site is affected by the property value configured through the inline editor.

Adding scripts and styles for inline editors

To add JavaScript and CSS styles required by your inline editors (including the script file containing the editor's registration code), we recommend placing script and stylesheet files into sub-folders under the ~/Content/InlineEditors directory of your MVC project (you may need to create the InlineEditors directory). For example, use sub-folders that match the identifiers of individual inline editors, or a Shared sub-folder for assets used by multiple editors.

The system automatically creates bundles containing all .js and .css files located under ~/Content/InlineEditors. The bundles are then linked on all pages with page builder editable areas. Inline editor scripts and styles are only included in the administration bundles, which are linked when pages are displayed in Edit mode within the Pages application of Kentico.

The same bundles also contain script and stylesheet files added for widgets in the ~/Content/Widgets directory and sections in the ~/Content/Sections directory.

Notes – Scripts

  • Avoid linking or executing scripts directly within the views of inline editors. This could lead to duplicated scripts on pages containing multiple widgets that use the editor.

Notes – Styles

  • To prevent your editor styles from overriding the site's styles, add a prefix to all CSS selectors used for the editor (for example custom-editor-class).
  • To prevent the editor's styles from being overridden by the site's styles, make all CSS selectors used for the editor as specific as possible. If necessary, use the !important rule for critical selectors.
  • Do not make any assumptions about the relative order of the source CSS in the resulting bundles – individual stylesheet files contained in the bundle may or may not precede each other.

Was this page helpful?