Using Sitefinity's Selectors in Custom Field Controls - Part 1 - Page Selector Field

Using Sitefinity's Selectors in Custom Field Controls - Part 1 - Page Selector Field

November 30, 2011 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.

This blog post is the first part of a series that will describe how to use the various Sitefinity selectors in your own custom field controls. Selectors are very useful when you need to pick an existing item from your project - page, user, role, image, etc.

The first part will describe how to use the GenericPageSelector control to be able to select a single existing page from your sitemap.

At the end of this post there is a link to the full working project that contains the different field controls. This file will be updated periodically to include the new field controls in the next parts of this series.

Basics

The base class for all field controls is Telerik.Sitefinity.Web.UI.Fields.FieldControl. Our PageSelectorField inherits directly from it. When you define a new field control you need to specify its "DefinitionElement" and "FieldDefinition" classes. Using the

[FieldDefinitionElement(typeof(PageSelectorFieldElement))]

attribute you assign PageSelectorFieldElement to the field control. This class inherits from FieldControlDefinitionElement and is very simple. Basically you need a constructor, you need to override

public override DefinitionBase GetDefinition()

where you return a new instance of your "FieldDefinition" class - in this case

return new PageSelectorFieldDefinition(this);

and you need to override

public override Type DefaultFieldType

to return the type of your field -

get
{
    return typeof(PageSelectorField);
}

The PageSelectorFieldDefinition inherits from the base FieldControlDefinition class and is very simple as well. You can check the code for details.

Your field control needs an .ascx template and a JavaScript file that will hold the client-side logic. These files are marked as Embedded resources and are named PageSelectorField.ascx and PageSelectorField.js. In the template file you define two conditional templates and in the "Write" template you put the controls that will be needed to edit your field's value. There is an instance of RadWindowManager and one RadWindow dialog, since we'll be using RadWindow as a popup dialog to select the page.

In order to register this additional dialog add a Global.asax file and add the following lines to it:

protected void Application_Start(object sender, EventArgs e)
{
    Bootstrapper.Initialized += new EventHandler<Telerik.Sitefinity.Data.ExecutedEventArgs>(Bootstrapper_Initialized);
}
 
void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e)
{
    Telerik.Sitefinity.Web.UI.Dialogs.RegisterDialog<SelectorFields.PageSelector.PageSelectorFieldDialog>();
}

Field Specifics

We'll be storing the selected page in the form <Page_Guid>;<Page_Titles_Path>. So a typical value saved in the database would be "0f642308-4191-4fd7-9a91-8d007b5b7c67;Home Page > Products > Sitefinity". This is needed to prevent additional retrieving of the breadcrumb titles on the client side when retrieving the field's value. You can change that to your liking.

The field control overrides the following methods:

public override void Configure(IFieldDefinition definition)
 
protected override void InitializeControls(GenericContainer container)
 
public override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
 
public override IEnumerable<ScriptReference> GetScriptReferences()

that are part of the abstract FieldControl class. In the template there is a SitefinityLabel control that shows the currently selected page and a HyperLink that opens the popup dialog. You can see how the different events are hooked in PageSelectorField.js.

The popup dialog has its own .ascx template and JavaScript file - PageSelectorFieldDialog.ascx and PageSelectorFieldDialog.js, which are also marked as EmbeddedResource. Its class - PageSelectorFieldDialog - inherits from a base class for such dialogs - AjaxDialogBase. This class also overrides GetScriptReferences() and GetScriptDescriptors() to register the client side fields and scripts that are needed for it.

In the dialog template we use the GenericPageSelector, which we register with the following markup:

<sitefinity:GenericPageSelector
                id="GenericPageSelector1"
                runat="server"
                RootNodeID="F669D9A7-009D-4d83-DDAA-000000000002"
                WebServiceUrl="~/Sitefinity/Services/Pages/PagesService.svc/"
                ShowOnlySelectedAsGridOnLoad="true"
                   MarkItemsWithoutTranslation="true"
                AllowMultipleSelection="false" />

You can customize this according to your needs. The RootNodeID is constant and is the page ID of site maps front-end root.

There are some events hooked for the Done and Cancel buttons. The currently selected page is may be retrieved using the following code:

var selectedValue = this.get_pageSelector().get_selectedItem(); 

Then this value is returned after closing the dialog using

dialogBase.close(selectedValue);

Back in the field control's JavaScript file, the

_windowClosed: function (sender, args) { }

event is raised and you can retrieve the selected page with

var selectedPage = args.get_argument();

The selectedPage object contains various properties about the page you have selected, of which we will use two - .Id and .TitlesPath. We'll assign a composed value the field's .value property, which will be persisted to the database after saving.

Since the field binds client-side, when it is loaded with the value from the database, the client-side method

set_value: function (value) { }

is called, where we extract the Titles part of the value and set the Text of the while label that shows the currently selected page with

jQuery(this._selectedPageLabel).html(value.substring(37));

The field is basically ready. You can now register a new custom field of this type for some Content type - e.g. News. Go to the "Custom Fields for news" screen and add a new field with the following settings:

Registering a Page Selector Field

After saving the changes you can go edit a News item and you will get the new field in action that should look like this:

Page Selector Field in Action

An finally a link to the full project - SelectorFields.zip

P.S. I attached the same project but without using RadWindow for the popup dialog. This is a more lightweight version that does not require to register the dialog in Global.asax and is less prone to errors when using the field control in custom modules - SelectorFieldsNoRadWindow 

progress-logo

The Progress Guys

View all posts from The Progress Guys on the Progress blog. Connect with us about all things application development and deployment, data integration and digital business.

Comments
Comments are disabled in preview mode.
Topics
 
 
Latest Stories in
Your Inbox
Subscribe
More From Progress
d12fcc0bdb669b804e7f71198c9619a7
5 Questions Automakers Should Ask to Improve Asset Uptime
Download Whitepaper
 
SF_MQ_WCM
2018 Gartner Magic Quadrant Web Content Management (WCM)
Download Whitepaper
 
What-Serverless-Means-For-Enterprice-Apps-Kinvey
What Serverless Means for Enterprise Apps
Watch Webinar