0

I want to have simple form validation on the STATES dropdown if and only if the country value is equal to USA or CANADA.

My validation works so far but its not dependent on the selection of USA or CANADA. Basically right now it will force you to select a state even if you select a country other than USA or CANADA.

<div class="row">
<div class="form-group" ng-class="{ 'has-error' : participantForm.country.$invalid && (!participantForm.country.$pristine || isSubmitted) }">
    <div class="col-sm-6 key">Country<span class="req">*</span>:</div>
    <div class="col-sm-6 val">
        <select ng-model="participant.country" name="country" class="form-control" required ng-options="country.Key as country.Value for country in countries">
            <option value="">SELECT</option>
        </select>
        <p ng-show="participantForm.country.$error.required && (!participantForm.country.$pristine || isSubmitted)" class="help-block">Select a country.</p>
    </div>
</div>

<div class="row">
<div class="form-group" ng-class="{ 'has-error' : participantForm.state.$invalid && (!participantForm.state.$pristine || isSubmitted) }">
    <div class="col-sm-6 key">US State or Canadian Province:</div>
    <div class="col-sm-6 val">
        <select ng-model="participant.state" name="state" class="form-control" required ng-options="state.Key as state.Value for state in states">
            <option value="">SELECT</option>
        </select>
        <p ng-show="participantForm.state.$error.required && (!participantForm.state.$pristine || isSubmitted)" class="help-block">Your state is required for USA or Canada.</p>
    </div>
</div>

Tetsuya Yamamoto
  • 24,297
  • 8
  • 39
  • 61
codeNinja
  • 1,442
  • 3
  • 25
  • 61
  • maybe something like a conditional required? https://stackoverflow.com/questions/13466133/how-can-i-conditionally-require-form-inputs-with-angularjs – ken lacoste Jul 31 '17 at 04:17

1 Answers1

0

If you give a value to the name property of the wrapping form element, AngularJS should automatically put an object on $scope by that name. For example, if you have the following:

<form name="participantForm">
    <input name="state" />
</form>

$scope.participantForm will be an angular supplied object that allows you to access info about the form on the page. In addition to that, if there is a name property on a form input element, there will also be an angular supplied object that is a property of the form: $scope.participantForm["state"] You actually use that in your view logic right now.

You should remove the "required" attribute on the select input element for the state/province so that it stops always requiring an input.

Instead, you should have a function that fires whenever the value of the state/province input changes, checks the value of the country field, and then manually sets the validity of the state/province field appropriately. The function may look like this:

$scope.validateStateField = function() {
    var isValid = true;
    var country = $scope.participant.country;
    if (country === "USA" || country === "Canada") {
        var state = $scope.participant.state;
        isValid = state != null && state !== '';
    }
    $scope.participantForm["state"].$setValidity("required", isValid);
}

If you ensure that this function runs when the state field changes and when the user tries to submit the form, then you'll not only change the validity of the input appropriately but you'll also have a correct value to check before you proceed with submission logic:

if ($scope.participantForm.$valid) {
    // Proceed because everything checks out
}

I believe there are also ways to create custom validators that are more native to Angular, but this is how I tend to manually approach dependent validation.