SharePoint Dragons

Nikander & Margriet on SharePoint

The riddle of the five drop down lists with unique values

In a way, this post is a follow up of blog post https://sharepointdragons.com/2012/04/18/adding-jquery-to-a-visual-web-part-and-then-implement-parentchild-radio-buttons/. If you know your way around visual web parts or user controls, you don’t need to read it per se. If you don’t understand the contents of this post, it’s advisable to read it first.

Question: Suppose you have five drop down lists with an identical set of values (1-5 in this example), and suppose each selected value within this group of five lists needs to be unique. How do you implement that?

Answer: Well, a good way to that would be to use jQuery to handle the client-side validation, and implement a server-side version that kicks in if JavaScript is disabled or circumvented. The code below consists of a user control (.ascx) used in a visual web part and it’s code behind file.

Please note: The user control contains a CustomValidator control that doesn’t use the ControlToValidate property. This is because we’re not validating a specific control, instead we’re validating all list controls.This does mean that the Value property of the arguments parameter always contains an empty string.

Here’s the code for the user control (*.ascx):

<%@ Assembly Name=”$SharePoint.Project.AssemblyFullName$” %>
<%@ Assembly Name=”Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”SharePoint” Namespace=”Microsoft.SharePoint.WebControls”
    Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”Utilities” Namespace=”Microsoft.SharePoint.Utilities” Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”asp” Namespace=”System.Web.UI” Assembly=”System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ %>
<%@ Import Namespace=”Microsoft.SharePoint” %>
<%@ Register TagPrefix=”WebPartPages” Namespace=”Microsoft.SharePoint.WebPartPages”
    Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Control Language=”C#” AutoEventWireup=”true” CodeBehind=”VisualWebPart1UserControl.ascx.cs”
    Inherits=”VisualWebPartProject1.VisualWebPart1.VisualWebPart1UserControl” %>
<asp:Label ID=”Label1″ runat=”server” Text=”Label”></asp:Label>
<SharePoint:ScriptLink ID=”ScriptLink1″ runat=”server” Name=”~sitecollection/SiteAssets/MyAssets/jquery-1.7.js” />

<script type=”text/javascript”>
    // Contains a list of priority values and the amount of occurrences.
    // E.g.: value 1 is selected 0 times, value 2 is selected 3 times.
    var _arrPrios;

    // Resets all priority values to zero occurrences.
    function Init() {
        // First is dummy entry, this makes it easier to understand the mapping between array index position and drop down list values.
        _arrPrios = [0, 0, 0, 0, 0, 0];
    }
   
    // Checks if all drop down lists contain a unique value.   
    function ValidateLists(src, args) {
        Init();
       
        // Select all priority drop down lists.
        $(“#divPrioLists select :selected”).each(function () {
            AddSelectedValue($(this).val());
        });
       
        // Skip first dummy entry (index = 0).       
        for (var i = 1; i < _arrPrios.length; i++) {
            if (_arrPrios[i] != 1) {               
                args.IsValid = false;
                return false;
            }
        }       

        args.IsValid = true;
    }

    // Count occurrences for every selected value (e.g. end user selected “1” 0 times, “2” 3 times.
    function AddSelectedValue(intValue) {
        _arrPrios[intValue] = ++_arrPrios[intValue];
    }
</script>

<asp:CustomValidator id=”CustomValidator2″ runat=”server” ErrorMessage = “All priority lists must have unique values”
ClientValidationFunction=”ValidateLists” OnServerValidate=”ValidateLists” >
</asp:CustomValidator>

<div id=”divPrioLists”>

<asp:DropDownList ID=”list1″ runat=”server”>
<asp:ListItem Text=”1″ Value=”1″ />
<asp:ListItem Text=”2″ Value=”2″ />
<asp:ListItem Text=”3″ Value=”3″ />
<asp:ListItem Text=”4″ Value=”4″ />
<asp:ListItem Text=”5″ Value=”5″ />
</asp:DropDownList>

<asp:DropDownList ID=”list2″ runat=”server”>
<asp:ListItem Text=”1″ Value=”1″ />
<asp:ListItem Text=”2″ Value=”2″ />
<asp:ListItem Text=”3″ Value=”3″ />
<asp:ListItem Text=”4″ Value=”4″ />
<asp:ListItem Text=”5″ Value=”5″ />
</asp:DropDownList>

<asp:DropDownList ID=”list3″ runat=”server”>
<asp:ListItem Text=”1″ Value=”1″ />
<asp:ListItem Text=”2″ Value=”2″ />
<asp:ListItem Text=”3″ Value=”3″ />
<asp:ListItem Text=”4″ Value=”4″ />
<asp:ListItem Text=”5″ Value=”5″ />
</asp:DropDownList>

<asp:DropDownList ID=”list4″ runat=”server”>
<asp:ListItem Text=”1″ Value=”1″ />
<asp:ListItem Text=”2″ Value=”2″ />
<asp:ListItem Text=”3″ Value=”3″ />
<asp:ListItem Text=”4″ Value=”4″ />
<asp:ListItem Text=”5″ Value=”5″ />
</asp:DropDownList>

<asp:DropDownList ID=”list5″ runat=”server”>
<asp:ListItem Text=”1″ Value=”1″ />
<asp:ListItem Text=”2″ Value=”2″ />
<asp:ListItem Text=”3″ Value=”3″ />
<asp:ListItem Text=”4″ Value=”4″ />
<asp:ListItem Text=”5″ Value=”5″ />
</asp:DropDownList>

</div>

<asp:Button ID=”btnSubmit”  runat=”server” Text=”Submit” />

Here’s the code for the code-behind file of the user control:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

namespace VisualWebPartProject1.VisualWebPart1
{
    public partial class VisualWebPart1UserControl : UserControl
    {

        protected override void OnInit(EventArgs e)
        {           
            // At this point, on a postback, the page hasn’t been validated yet.
            // You could call Page.Validate() explicitly or follow the normal flow of events.           
        }

        protected override void OnLoad(EventArgs e)
        {
            // At this point, on a postback, the page hasn’t been validated yet.
            // You could call Page.Validate() explicitly or follow the normal flow of events.           
        }

        protected override void OnPreRender(EventArgs e)
        {
            // The page has been validated on a postback.
            if (Page.IsPostBack && Page.IsValid)
            {

            }
        }

        // Contains a list of priority values and the amount of occurrences.
        // E.g.: value 1 is selected 0 times, value 2 is selected 3 times.
        private int[] _arrPrios = { 0, 0, 0, 0, 0, 0 };

        /// <summary>
        /// Server-side validation is equivalent to jQuery version, but kicks in in case end user disables JavaScript,
        /// or maliscuously tries to circumvent client-side validation.
        /// </summary>
        protected void ValidateLists(object source, ServerValidateEventArgs args)
        {
            // Register all selected values for all priority lists
            AddSelectedValue(list1, list2, list3, list4, list5);

            // Skip first dummy entry (index = 0).       
            for (int i = 1; i < _arrPrios.Length; i++)
            {
                if (_arrPrios[i] != 1)
                {
                    args.IsValid = false;
                    return;
                }
            }       

            args.IsValid = true;
        }

        /// <summary>
        /// Count occurrences for every selected value (e.g. end user selected “1” 0 times, “2” 3 times.
        /// </summary>       
        private void AddSelectedValue(params DropDownList[] args)
        {
            for (int i = 0; i < args.Length; i++)
            {
                var currentValue = Convert.ToInt32(args[i].SelectedValue);
                _arrPrios[currentValue] = ++_arrPrios[currentValue];
            }
        }
    }
}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: