J86
J86

Reputation: 15307

AngularJS Validation on <select> with a prompt option

I have the following code for a select drop down input that is styled in Bootstrap.

<select class="form-control" name="businessprocess" ng-model="businessprocess" required>
    <option value="">-- Select Business Process --</option>
    <option value="C">Process C</option>
    <option value="Q">Process Q</option>
</select>

Before the user is able to submit this form, he or she must select a business process.

So I have put the required directive on the select statement, however because the first option tag has -- Select Business Process -- that still counts as a selected option, and thus the required flag is met, and therefore the form validates even though no actual Business Process is selected.

How can I overcome this issue?

Thank You.

Upvotes: 16

Views: 53395

Answers (9)

JanBrus
JanBrus

Reputation: 1520

This works for me. Form is invalid until user selects any other value than "Choose..."

<select name="country" id="country" class="form-control" formControlName="country" required>
    <option selected value="">Choose...</option>
    <option *ngFor="let country of countries">{{country.country}}</option>
</select>

Upvotes: 0

tharindu
tharindu

Reputation: 523

Use the following code snippet

<select class="form-control" name="businessprocess" ng-model="businessprocess">
    <option value="A" disabled selected hidden>-- Select Business Process --</option>
    <option value="C">Process C</option>
    <option value="Q">Process Q</option>
</select>

Upvotes: 1

Radim K&#246;hler
Radim K&#246;hler

Reputation: 123901

This approach could/should solve your issue:

1) declare the options inside of your scope:

$scope.processes = [
    { code: "C", name: "Process C" },
    { code: "Q", name: "Process Q" }
];

And 2) use this declaration:

<select class="form-control" name="businessprocess" ng-model="businessprocess" required
    ng-options="c.code as c.name for c in processes" >
    <option value="">-- Select Business Process --</option>
</select>

The trick here is in fact, that during the angular cycles, will firstly fix the issue that the the current value is not among the processes options. So, the default would be set to:

<option value="">-- Select Business Process --</option>

and required will be working as expected (more details)

Upvotes: 30

&#214;mer An
&#214;mer An

Reputation: 664

Add "disabled" to the first option:

<select class="form-control" name="businessprocess" ng-model="businessprocess" required>
<option value="" disabled>-- Select Business Process --</option>
<option value="C">Process C</option>
<option value="Q">Process Q</option>

Upvotes: 0

userNumber2016
userNumber2016

Reputation: 1

Maybe this code, can be usefull for this... in this case the form is called myform

<select ng-model="selectX" id="selectX" name="selectX"  required>
                                            <option  value="" ></option>
                                            <option  value="0" >0</option>
                                            <option value="1">1</option>
                                          </select>

    <span style="color:red" ng-show="myform.selectX.$dirty && myform.selectX.$invalid">
    <span ng-show="myform.selectX.$error.required">Is required.</span>
    </span> 

Upvotes: -1

youhammi
youhammi

Reputation: 524

a best way and straight one is to use:

HTML

<select name="businessprocess" ng-model="businessprocess"  required>
        <option selected disabled value="">-- Select Business Process --</option>
        <option ng-repeat="v in processes" value="{{v.id}}">{{v.value}}</option>
</select>

Upvotes: 2

paulohenriquevn
paulohenriquevn

Reputation: 21

JS



    angular.module('interfaceApp')
  .directive('requiredSelect', function () {
    return {
      restrict: 'AE',
      require: 'ngModel',
      link: function(scope, elm, attr, ctrl) {

        if (!ctrl) return;
          attr.requiredSelect = true; // force truthy in case we are on non input element

          var validator = function(value) {
            if (attr.requiredSelect && ctrl.$isEmpty(value)) {
              ctrl.$setValidity('requiredSelect', false);
              return;
            } else {
              ctrl.$setValidity('requiredSelect', true);
              return value;
            }
          };

          ctrl.$formatters.push(validator);
          ctrl.$parsers.unshift(validator);

          attr.$observe('requiredSelect', function() {
            validator(ctrl.$viewValue);
          });
      }
    };
  });


Upvotes: 2

Maxim Shoustin
Maxim Shoustin

Reputation: 77910

You can try to add form, like:

HTML

<div ng-app="myApp" ng-controller="MyCtrl">
     <form name="mainForm">
    <select name="businessprocess" ng-model="businessprocess"  required>    
        <option value="">-- Select Business Process --</option>
        <option ng-repeat="v in processes" value="{{v.id}}">{{v.value}}</option>
    </select>
    <span class="error" ng-show="mainForm.businessprocess.$error.required">required</span>
</form>
</div>

js

angular.module('myApp', []);

function MyCtrl($scope, $timeout) {
   $scope.processes = [{
        id: "C",
        value: "Process C"
    }, {
        id: "Q",
        value: "Process Q"
    }];
}

Demo Fiddle

Upvotes: 1

Frankjs
Frankjs

Reputation: 565

you can initial the value of selector in controller:

<select class="form-control" name="businessprocess" ng-model="businessprocess">
    <option value="A">-- Select Business Process --</option>
    <option value="C">Process C</option>
    <option value="Q">Process Q</option>
</select>

in Controller:

$scope.businessprocess = "A" ;

or "C","Q",whatever you want, so the select will always have value. i think you don't need "required" here in select.

If you don't want an init a value. also do some extra effect when user don't select it.

<select class="form-control" name="businessprocess" ng-model="businessprocess" myRequired>
    <option value="">-- Select Business Process --</option>
    <option value="C">Process C</option>
    <option value="Q">Process Q</option>
</select>

then write the directive:

model.directive("myRequired", function() {
    return {
        restrict: 'AE',
        scope: {},
        require: 'ngModel',
        link: function(scope, iElement, iAttrs) {
                if(iElement.val() == ""){
                    //do something
                    return;
                } else {
                    //do other things
                }
            });
        }
    };
});

Upvotes: 4

Related Questions