Categories
Bloggers
Blogs RSS feed

Sitefinity Custom Form Widget with Dependent Dropdowns

by Stanislav Velikov
This blog post provides a sample and tutorial on how to implement a Sitefinity form widget with related dropdowns. Once you select a value from one of the dropdowns, the send dropdown is populated with values depending on the first one. For the sample I have used a list of states.

Here you can download the sample code for the form control. Register the new form widget using Sitefinity Thunder visual studio extension, here is the related documentation on how to register a form control or any other widget using Thunder.

A good approach is to generate the form widget using Thunder and from then on extend the widget implementation to support dependent dropdowns. Here is the documentation on generating form widgets with Thunder.

The template:
The form control with related dropdowns will use two RadComboBox controls on its template, I have chosen RadComboBox instead of ASP.NET DropDownList control because RadComboBox control exposes its own client site API. In the template of the control define two RadComboBox controls, one with an ID of State which is the first ComboBox and the second control with an ID of DependentState to display the info bound to the control once the first RadComboBox value is selected.

<telerik:RadComboBox ID="State" CssClass="sfTxt" runat="server">
</telerik:RadComboBox>
<hr />
<telerik:RadComboBox ID="DependantState" CssClass="sfTxt" runat="server">
</telerik:RadComboBox>

The class:
In the Class for the control add references to the RadComboxBoxes that reside in the template:

protected virtual RadComboBox ddl
        {
            get
            {
                return this.Container.GetControl<RadComboBox>("State", true);
            }
        }
 
        protected virtual RadComboBox ddlDependant
        {
            get
            {
                return this.Container.GetControl<RadComboBox>("DependantState", true);
            }
        }

In InitializeControls method the first RadComboBox is bound to a list of states or another datasource.

protected override void InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container)
       {
           this.ddl.DataSource = statesList();
           this.ddl.DataTextField = "Value";
           this.ddl.DataValueField = "Key";
           this.ddl.DataBind();
           
       }

In GetScriptDescriptors method the RadComboBoxes are added as ComponentProperty because the control exposes its own API. This way the API will be made available in the client side component of the form widget.

public override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
       {
           var descriptor = new ScriptControlDescriptor(typeof(States).FullName, this.ClientID);
           descriptor.AddComponentProperty("dropdown", this.ddl.ClientID);
           descriptor.AddComponentProperty("dropdownDependant", this.ddlDependant.ClientID);
           descriptor.AddProperty("dataFieldName", this.MetaField.FieldName);
 
           return new[] { descriptor };
       }

The client side component:
In the JavaScript for the control I have implemented a function _fillStates: function (val) which populates the states in both dropdowns. The two most important functions are get_value and set_value which utilize the API of RadComboBox to save the values of the two RadComboBoxes.

get_value: function () {
       var arrayOfValues = [];
       arrayOfValues.push(this._dropdown._highlightedItem._text);
       arrayOfValues.push(this._dropdownDependant._highlightedItem._text);
 
       return arrayOfValues.toString();
   },
 
   // Sets the value of the dropdown control depending on DisplayMode.
   set_value: function (values) {
       if (values) {
           var arrayOfValues = values.split(',')
           this._dropdown.set_text(arrayOfValues[0]);
           this._dropdownDependant.set_text(arrayOfValues[1]);
       }
   },

3 comments

Leave a comment
  1. Craig Jan 17, 2014
    I like where you are going with this blog post Stanislav.  Your example suggest having one field control with two RadComboBoxes.  

    What I am wondering is there a way to have two independent form fields talk to each other.  For example, if I add two drop down lists to a form can I get this to talk to each other?  Or can I create a modified version of the drop down list field control that could do this?

    Thanks,
    Craig

  2. Stanislav Jan 23, 2014
    With the form controls placed on a form there is no dependency available for the form controls in which they are aware of other form controls placed on the same form so I believe you want to transfer the selected data from one control to another where the problem is that when all form controls are placed on a form all controls must be completely rendered for selecting data from one control to occur which make communication between controls hard when the controls are separate widgets.

    An approach here is when for example form control select a value to save the value client side for example in query string or write temporary files on the client from which another form control will read the value. Here I think having the dependent widgets in one control sharing a single context is better approach.
  3. Richard Mar 10, 2014

    Hi - I haven't tried to implement this yet, but will it be possible to add more than two? Thanks

    Leave a comment