How can I achieve the effect of multiple validation groups on a single validation control?

1.6k Views Asked by At

I need to be able to apply multiple validation groups to some of the controls on my page, because for each of the three submit "modes", there is a different set of required fields.

I have three submit buttons, and each one has its own validation group (reject, approve, and save). "Reject" doesn't actually have any required fields currently, but may in the future. "Save" only requires "first name" and "last name", while "approve" requires "first name", "last name", as well as "group name".

I tried simply putting multiple validation groups in the attribute value (as in the code below), but the validation didn't fire at all.

I also tried not specifying a group at all in an attempt to just have the validation always fire, but again again, it didn't fire at all.

<div>
    <label for='<%= txt_FirstName.ClientID %>'>First Name</label>
    <asp:TextBox ID="txt_FirstName" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="rfv_FirstName" runat="server" text="Required"
        ControlToValidate="txt_FirstName" ValidationGroup="approve save">
    </asp:RequiredFieldValidator>
</div>
<div>
    <label for='<%= txt_LastName.ClientID %>'>Last Name</label>
    <asp:TextBox ID="txt_LastName" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ID="rfv_LastName" runat="server" text="Required"
        ControlToValidate="txt_LastName" ValidationGroup="approve save">
    </asp:RequiredFieldValidator>
</div>
<div>
    <label for='<%= ddl_GroupName.ClientID %>'>Group Name</label>
    <asp:DropDownList ID="ddl_GroupName" runat="server"></asp:DropDownList>
    <asp:RequiredFieldValidator ID="rfv_GroupName" runat="server" text="Required"
        ControlToValidate="ddl_GroupName" ValidationGroup="approve">
    </asp:RequiredFieldValidator>
</div>
<div>
    <asp:Button ID="btn_Reject" runat="server" Text="Reject"
        ValidationGroup="reject" OnClick="btn_Reject_Click" />
    <asp:Button ID="btn_Approve" runat="server" Text="Approve"
        ValidationGroup="approve" OnClick="btn_Approve_Click" />
    <asp:Button ID="btn_Save" runat="server" Text="Save"
        ValidationGroup="save" OnClick="btn_Save_Click" />
</div>

I'm certain I can achieve the desired effect with some additional code, or duplicated validator controls for each validation group, but I was hoping the webforms framework would have a simpler, built-in way to do this.

UPDATE (2018-01-02):
The question "Is it possible to assign Multiple Validation Groups to a single Validation Control?" is a special case of my own. It has a single control in multiple groups, whereas I have multiple controls with multiple overlapping groups. Additionally, the answer proposes having a validation control for each input/group combination. This is a terrible solution because, among other things, it violates the DRY (don't repeat yourself) programming principle and makes maintenance/enhancements more difficult.

The above also links the question "How to validate against Multiple validation groups?". That question is a completely different issue (validation groups within validation groups), and its answer proposes custom javascript that would need to be written for every submit button, on every page that requires multiple validation groups.

I am looking for a general case solution that I can write/implement once and apply to the entirety of the web application, and thus I do not consider my question a duplicate of the above mentioned questions.

UPDATE (2018-01-03):
Between other questions/articles I've encountered while researching my problem, as well as the gracious assistance of a.bajorinas and Sunil, I've established that it is not possible to have multiple validation groups on a validation control out-of-the-box, and custom code will be required to achieve the desired effect. I've updated the question accordingly, to assist anyone looking to achieve this in the future.

I'll be testing a solution that incorporates elements from both a.bajorinas' and Sunil's answers and will hopefully be able to provide an update afterward.

2

There are 2 best solutions below

1
On

The only thing I can think of for your desired use case, is setting ValidationGroup for your validators in code behind on button click, keep in mind that this would first perform a postback and then validate the controls which might not be ok for you.

protected void btn_save_click(object sender, EventArgs e){
    rfv_FirstName.ValidationGroup = "save";
    Page.Validate("save");
    if (Page.IsValid)
    {
        //logic if validators pass
    }
}

This will let you reuse validators for multiple groups. Also in my linked posted, one of the comments to the selected answer is "It is not possible to assign multiple groups to a validation control"

6
On

ASP.Net does not support multiple validation groups. However, with a little bit of JavaScript code you can make it support multiple validation groups. What you need to do is override the standard JavaScript function of IsValidationGroupMatch. This function is part of the standard validation library in ASP.Net.

At bottom of your aspx page, just add the script tag given below. Note that this script is just before closing form, body and html tags, which is important when overriding a JavaScript function.

<script type="text/javascript">
            window["IsValidationGroupMatch"] = function (control, validationGroup) {
                if ((typeof (validationGroup) == "undefined") || (validationGroup == null)) {
                    return true;
                }
                var controlGroup = "";
                var isGroupContained = false;
                if (typeof (control.validationGroup) == "string") {
                    controlGroup = control.validationGroup;
                    var controlGroupArray = [];
                    if (validationGroup.indexOf(",") > -1) {
                        controlGroupArray = validationGroup.split(",");// validationGroup.split(",");
                    }
                    for (var i = 0; i < controlGroupArray.length; i++) {
                        if (controlGroupArray[i].trim() == controlGroup.trim()) {
                            isGroupContained = true;
                        }
                    }
                }
                return (controlGroup == validationGroup || isGroupContained);
            }
        </script>
    </form>
</body>
</html>

Once you do this, then you can add a comma delimited list of validation groups for the button that validates multiple validation groups as in example below. In example below a button with id of btnMultipleValidationGroups is validating group1 as well as group2.

<div>
            TextBox1 : 
            <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
            <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="TextBox1 needs input"  ControlToValidate="TextBox1" ForeColor="Red" ValidationGroup="group1"></asp:RequiredFieldValidator>

            <br />
            <br />
            TextBox2 : 
            <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
            <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ErrorMessage="TextBox2 needs input"  ControlToValidate="TextBox2" ForeColor="Red" ValidationGroup="group2"></asp:RequiredFieldValidator>
            <br />
            <br />
            TextBox3 :
             <asp:TextBox ID="TextBox3" runat="server"></asp:TextBox>
            <asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" ErrorMessage="TextBox3 needs input"  ControlToValidate="TextBox3" ForeColor="Red" ValidationGroup="group3"></asp:RequiredFieldValidator>

            <br />
            <br />
        </div>
        <asp:Button ID="btnMultipleValidationGroups" runat="server" Text="Validate group1 and group2" ValidationGroup="group1,group2" OnClick="btnMultipleValidationGroups_Click" />
        <asp:Button ID="btnGroup1" runat="server" Text="Validate only group1" ValidationGroup="group1" OnClick="btnGroup1_Click" />
        <asp:Button ID="btnGroup2" runat="server" Text="Validate only group2" ValidationGroup="group2" OnClick="btnGroup2_Click" />