How to Create a MultiPage Field Control in Sitefinity

How to Create a MultiPage Field Control in Sitefinity

Posted on June 03, 2013 0 Comments

The content you're reading is getting on in years
This post is on the older side and its content may be out of date.
Be sure to visit our blogs homepage for our latest news, updates and information.

Most of you have already used Sitefinity's out-of-the-box PageField control, allowing you to select pages from the SiteMap in content modules. In this blog post I'm going to show you how to create your own custom MultiPage field control, that can be used to select multiple pages in Sitefinity CMS. I'm not going to cover the basics of the process for creation of field controls. We already have documentation on this. You might want to check it here.

In my example I've used a sample field control, generated by Sitefinity Thunder. As you know, we have the template for the field control, which contains all controls, that will appear in the backend, once you add the custom field control to a module. The most important part of the template is the FlatSelector, which will handle the logic for selecting items from particular content type - in our case Pages. We pass the PageService URL to the ServiceUrl property of the FlatSelector. In the DataMemberInfo we specify the value what property of the content type will appear in the selector - we choose Title, to be able to select pages by Title. One important FlatSelector property is AllowMultipleSelection. When it is set to True you will be able to select multiple items, and if it is False, it will become a single item selector again.

<sitefinity:FlatSelector ID="pageSelector" runat="server" ItemType="Telerik.Sitefinity.Pages.Model.PageNode"
        DataKeyNames="Id" ShowSelectedFilter="false" AllowPaging="false" PageSize="10" BindOnLoad="true"
        AllowSearching="true" ShowProvidersList="true" InclueAllProvidersOption="false"
        SearchBoxTitleText="Filter by Title" ShowHeader="true" AllowMultipleSelection="true"
        ServiceUrl="~/Sitefinity/Services/Pages/PagesService.svc/"  >
        <DataMembers>
            <sitefinity:DataMemberInfo ID="DataMemberInfoSelectedPage" runat="server" Name="Title" IsExtendedSearchField="true" HeaderText="Title">
                    <span>{{Title.Value}}</span>
            </sitefinity:DataMemberInfo>
        </DataMembers>
    </sitefinity:FlatSelector>

In the MultiPageSelector.cs we get all controls from the template and pass them to the javascript as Element or Component properties, respectively.

public override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
       {
           List<ScriptDescriptor> descriptors = new List<ScriptDescriptor>();
 
           ScriptControlDescriptor descriptor = base.GetScriptDescriptors().Last() as ScriptControlDescriptor;
 
           descriptor.AddElementProperty("selectButton", this.SelectButton.ClientID);
           descriptor.AddElementProperty("lnkDone", this.DoneButton.ClientID);
           descriptor.AddElementProperty("lnkCancel", this.CancelButton.ClientID);
           descriptor.AddComponentProperty("pageSelector", this.PageSelector.ClientID);
 
           descriptors.Add(descriptor);
 
           return descriptors.ToArray();
       }

Most of our logic is in the javascript, so let's get to it. The js file contains the get_value and set_value properties, as well as get and set for: the page selector, the selection button, the Done and Cancel buttons. Notice we have two additional properties get_uiCulture and set_uiCulture. The get property returns the current UiCulture. In the set property we set the UiCulture to our PageSelector and we also set the itemsFilter property of your field control to the following filterExpression: "AvailableLanguages.Contains(\"" + culture + "\")". This way we make sure that, depending on the current culture, the selector will return only items that have such language translations. It is also important to implement the ILocalizableFieldControl interface in the javascript to use the multi language support.
The following part of the code adds a button click handler to each button:
if (this._selectButton) {
            this._selectButtonClickDelegate = Function.createDelegate(this, this._selectButtonClicked);
            $addHandler(this._selectButton, "click", this._selectButtonClickDelegate);
        }
 
        if (this._lnkDone) {
            this._PagesDoneSelectingDelegate = Function.createDelegate(this, this._PagesDoneSelecting);
            $addHandler(this._lnkDone, "click", this._PagesDoneSelectingDelegate);
        }
 
        if (this._lnkCancel) {
            this._PagesCancelDelegate = Function.createDelegate(this, this._PagesSelectorCloseHandler);
            $addHandler(this._lnkCancel, "click", this._PagesCancelDelegate);
        }

Take a look at the _selectButtonClicked function, where after opening the Page selector dialog we pass the ItemsFilter to the page selector again, so that it will display the selected value in the current language.
_selectButtonClicked: function (sender, args) {
       debugger;
       this._selectPagesDialog.dialog("open");
       this._dialogScrollToTop(this._selectPagesDialog);
       this.get_pageSelector().set_itemsFilter(this._itemsFilter);
       this.get_pageSelector().set_selectedKeys(this._value);
       this.get_pageSelector().dataBind();
       return false;
   },

Also, let's look at the _PagesDoneSelecting. When we are done selecting pages, we get their ids and populate the "VALUE" of the field control with the selection. We save an array of ids, that is why the field in the dynamic module must be of type Array of Guid.

_PagesDoneSelecting: function (sender, args) {
       this._selectPagesDialog.dialog("close");
      
       var arr = new Array();
       var selectedPages = this.get_pageSelector().get_selectedItems();
       for (var i = 0; i < selectedPages.length; i++) {
           arr.push(selectedPages[i].Id);
       }
       //SET THE VALUE
       this._value = arr;
 
       this._setSelectedItemsLabel(arr.length);
       return false;
   },

I believe we covered the essential parts of the field control implementation. In the video below you will see how to add it to your modules. Don't forget that the type of the property you'll add to your modules should be Array of Guids.



This field control can practically work with dynamic types, as well (after slight modifications). This can be done by changing the serviceUrl of the FlatSelector to the url of DynamicModule services.

Hope you like the blog post!
Zheyna Peleva headshot

Zheyna Peleva

Jen Peleva was a Principal frontend developer for the Sitefinity CMS.

Comments

Comments are disabled in preview mode.
Topics

Sitefinity Training and Certification Now Available.

Let our experts teach you how to use Sitefinity's best-in-class features to deliver compelling digital experiences.

Learn More
Latest Stories
in Your Inbox

Subscribe to get all the news, info and tutorials you need to build better business apps and sites

Loading animation