How to create a custom field control

From Sense/Net Wiki
Jump to: navigation, search
  •  
  •  
  •  
  •  
  • 100%
  • 6.3
  • Enterprise
  • Community
  • Planned

Overview

We introduce how to create a custom field control that allows you to store a list of values as related "metadata". How to customize field view and field editing options on the admin surface.


Steps

1. Add a the new field control to the solution

Add the new Field Control file to Source/SenseNet/Portal/UI/Controls/FieldControls folder. The file name must match with the ControlHint name applied on the CTD (MyFieldControl.cs). Add a script, which the field calls on init and initialize UI by.

protected override void OnInit(EventArgs e)
{
   UITools.AddScript("myCustomScript.js");
   base.OnInit(e);
}

2. Update CTD of the required content

On the chosen field add a new configuration option which allows to configure a custom field control:

  <Field name="myCustomField" type="LongText">
      ...
      <Configuration>
        <ControlHint>sn:MyFieldControl</ControlHint>
      </Configuration>
  </Field>

3. Create the script

In a custom script (e.g. /Root/Global/scripts/sn/SN.CallToAction.js) custom functions have to be defined that need to be executed on the field when new content is added or existing content is edited. The content of the LongText-field can be parsed here to a JSON string and pushed to an array. By hiding the longtext-field an displaying a newly created markup, that shows the array-elements separately, allows to manipulate them as metadata belonging to this filed.

Button = {
    Add: function () {
        var buttonPath = $('.innner-link-table .sn-button-innerlinkpath').val();
        var buttonText = $('.innner-link-table .sn-button-buttontext').val();
        var contentId = $('.innner-link-table .sn-button-contentId').val();
        var linkTarget = $('.innner-link-table .sn-button-target').val();
        var linkTitle = $('.innner-link-table .sn-button-title').val();
 
        // give metadata to functions
        Button.AddItemToList(buttonPath, buttonText, contentId, linkTitle, linkTarget);
        // a hidden textbox holds all metadata of all buttons
        Button.AddItemToHiddenTextbox(buttonPath, buttonText, contentId, linkTitle, linkTarget);
    },
 
    // add new button to buttonlist
    AddItemToList: function (buttonPath, buttonText, contentId, linkTitle, linkTarget) {
        // create newbutton markup
        ...
    },
    AddItemToHiddenTextbox: function (buttonPath, buttonText, contentId, linkTitle, linkTarget) {
        // add metadata as JSON to hidden textbox
        var tb = $('.sn-button-innerdata');
 
        var button = new Button.button(buttonPath, buttonText, contentId, linkTitle, linkTarget);
        if (tb.val() !== '') {
            buttonArray = JSON.parse(tb.val());
        }
        else {
            buttonArray = [];
        }
 
        buttonArray.push(button);
        tb.val(JSON.stringify(buttonArray));
    },
 
    // create this button with all metadata
    button: function (buttonPath, buttonText, contentId, linkTitle, linkTarget, id) {
        this.buttonPath = buttonPath;
        this.buttonText = buttonText;
        this.contentId = contentId;
        this.linkTitle = linkTitle;
        this.linkTarget = linkTarget;
        if (typeof id !== 'undefined')
            this.id = id;
        else
            this.id = 'button-' + buttonArray.length;
    },
    Load: function () {
 
        ...
    },
    Delete: function (id, $button) {
        ...
    },
    Edit: function (id, $button) {
        ...
    },
    Change: function ($button) {
        var tb = $('.sn-button-innerdata');
        var buttonPath = $button.find('.sn-button-innerlinkpath').val();
        var buttonText = $button.find('.sn-button-buttontext').val();
        var contentId = $button.attr('data-contentid');
        var linkTarget = $button.find('.sn-button-target').val();
        var linkTitle = $button.find('.sn-button-title').val();
 
        ...
 
        buttonArray = JSON.parse(tb.val());
        var button = new Button.button(buttonPath, buttonText, contentId, linkTitle, linkTarget, $button.attr('id'));
 
        for (var i = 0; i < buttonArray.length; i++) {
            if (buttonArray[i].id === $button.attr('id')) {
                buttonArray[i].buttonPath = button.buttonPath;
                buttonArray[i].contentId = button.contentId;
                buttonArray[i].buttonText = button.buttonText;
                buttonArray[i].linkTarget = button.linkTarget;
                buttonArray[i].linkTitle = button.linkTitle;
            }
        }
 
        tb.val('');
        tb.val(JSON.stringify(buttonArray));
        ...
    },
    Populate: function () {
        ...
 
    }
}

As you can see above we've defined some methods for the Button object like Add, Delete, Change, etc. These methods helps us to create or change markup of the field/buttonlist and if you check the change function you can see how the field values are transformed to a button object which is put as string into the actual Longtext field in the background.

4. Add custom field-control template

To display this new field one needs to create a new custom template for. In the /Root/Global/fieldcontroltemplates folder add a new folder with the name of the field-control (MyFieldControl). In this folder add BrowseTemplate.ascx and EditTemplate.ascx files, where you can define the appearance of the fields.

Related links