Search code examples
c#asp.net-mvcjquery-validateunobtrusive-validation

How to use unobtrusive validation to make an input field required field if another input field is empty?


I have a simple form with three different text boxes to enter the search criteria before a resultset can be returned. Among the three fields I want to make two fields conditionally required if the other one is empty.

In the attached screenshot the search form cannot be submitted without entering either the "Title" or "Performers" fields. It is fine if both fields have values. I wanted to achieve this by making "Title" as a required field when "Performers" is empty. But my code below doesn't work. I have the necessary validation at the server side. I am looking for a client side solution.

enter image description here

HTML Source code:

<form id="searchWorkForm">
        <div class="contourField textfield">
            <label for="searchWorkTitle" class="fieldLabel">Title</label>
            <div class="search-input">
                <a id="searchWork" href="#" style="z-index: 2000; margin-top: 0;"><img src="/images/profile-search.png" alt="" style="z-index: 1000;" id="profileSearch" /></a>
                <input type="text" name="searchWorkTitle" id="searchWorkTitle" class="text caps" value="" placeholder="Title" data-val="true" data-val-requiredif="title is mandatory" data-val-requiredif-otherpropertyname="searchWorkPerformer">
                <span class="field-validation-valid" data-valmsg-for="searchWorkTitle" data-valmsg-replace="true"></span>
            </div>
        </div>
        <div class="contourField textfield">
            <label for="searchWorkWriter" class="fieldLabel">Writers</label>
            <div class="wideInput">
                <input type="text" name="searchWorkWriter" id="searchWorkWriter" class="text caps" value="" placeholder="Writer Name">
                <span class="field-validation-valid" data-valmsg-for="searchWorkWriter" data-valmsg-replace="true"></span>
            </div>
        </div>
        <div class="contourField textfield">
            <label for="searchWorkPerformer" class="fieldLabel">Performers</label>
            <div class="wideInput">
                <input type="text" name="searchWorkPerformer" id="searchWorkPerformer" class="text caps" value="" placeholder="Performer Name" data-val="true">
                <span class="field-validation-valid" data-valmsg-for="searchWorkPerformer" data-valmsg-replace="true"></span>
            </div>
        </div>
</form>

Client side validation code:

$(function() {
    if ($.validator && $.validator.unobtrusive) {

        $.validator.addMethod("requiredif", function (value, element, params) {
            return !(value.length === 0 && $(params).val().length === 0);
        });

        $.validator.unobtrusive.adapters.add("requiredif", ["otherpropertyname"], function (options) {
            options.rules["requiredif"] = "#" + options.params.otherpropertyname;
            options.messages["requiredif"] = options.message;
        });
    }

    $("#searchWork").click(function() {

        if ($("#searchWorkForm").valid()) {
            // Make an Ajax Call and get the search result
        }
    });
}

Solution

  • You first need to move the $.validator.addMethod() and $.validator.unobtrusive.adapters.add() functions outside the $(function() { .. }

    But based on the description of what your wanting to validate, then the code in your $.validator.addMethod() method should first check if the 'other property' (searchWorkPerformer) has a value, and if so return true. If it does not, then check if searchWorkTitle has a value. If it has, then return true, otherwise its invalid, so return false.

    // scripts for jquery, jquery.validate and jquery.validate.unobtrusive
    <script>
        $.validator.addMethod("requiredif", function (value, element, params) {
            if ($(params).val().length === 0) {
                return true;
            } else if (value.length === 0) {
                return false;
            }
            return true;
        });
        $.validator.unobtrusive.adapters.add("requiredif", ["otherpropertyname"], function (options) {
            options.rules["requiredif"] = "#" + options.params.otherpropertyname;
            options.messages["requiredif"] = options.message;
        });
    
        $(function() {
            $("#searchWork").click(function() {
                if ($("#searchWorkForm").valid()) {
                    // Make an Ajax Call and get the search result
                }
            });
        }
    </script>
    

    Side note: requiredif does not really describe your validation - perhaps requiredifempty would be more appropriate since you only require a value if the other property is empty.