I have a select with options. I would like to initialize the select value regarding to the user logged ng-init="own = credentials.user_id".
It works when the user_id is equals to the value in the select.
But when it's not equals, the value selected is "?". So there is no error whereas it should be.
I would like to not selected this "?" and invalidate the form.
Do you have a solution ?
<div ng-class="{ 'error-select': myForm.lead.$error.required == true }"><span>Leader</span></div>
<select ng-model="lead" name="lead" ng-options="leader.user_id as leader.user_display_name for leader in leaders" ng-init="lead = credentials.user_id" required></select>
<div ng-class="{ 'error-select': myForm.own.$error.required == true }"><span>Leader</span></div>
<select ng-model="own" name="own" ng-options="own.user_id as own.user_display_name for own in owns" ng-init="own = credentials.user_id" required></select>
OUTPUT : user_id = 4
<select t ng-model="lead" name="lead" ng-options="leader.user_id as leader.user_display_name for leader in leaders" ng-init="lead = credentials.user_id" required="" class="ng-pristine ng-valid ng-valid-required">
<option value="0">Alexandre</option>
<option value="1">Antoine</option>
<option value="2">Zaaza</option>
<option value="3">toro</option>
<option value="4"selected="selected">Steffi</option>
</select>
<select t ng-model="own" name="own" ng-options="own.user_id as leader.user_display_name for own in owns" ng-init="own = credentials.user_id" required="" class="ng-pristine ng-valid ng-valid-required">
<option value="?" selected="selected"></option>
<option value="1">Alexandre</option>
<option value="2">Steffi</option>
</select>
This requirement is not so trivial and there could be several approaches to it. (I am not really sure the chosen one is the best.)
TL;DR
Here is the working demo.
What's going on ?
First things first: we need to understand what is actually happening.
A control's validity state (
$valid/$invalid) depends on the$modelValueor$viewValue. The key-point here is that is does not depend on the elements actualvalueproperty.When you try to set the
$modelValueto something that is not in theusersarray (e.g. 3), i.e. that there is no valid<option>element available, then Angular will set$modelValueand$viewValueto 3, but the<select>'svaluewill be either?(if you haven't added an empty<option>element) or whatever the value of the explicitely added empty<option>.But since tha validation is not based on the elements
valueeverything seems$validfrom arequiredstandpoint.A solution
One solution is to create a custom directive that has access to the elements
ngModelControllerand "hooks" itself to the$render()function.This directive will check if the element's
valueis?(which indicates an invalid$modelValue) and if so, set the$modelValue/$viewValueto something actually empty, which will correctly update the validity of the control (i.e. an invalid$modelValuewill trigger our directive's handler to reset that to something empty and therequiredconstaint won't be fulfilled).Here is the code:
See, also, this short demo.
A few points to note regarding the above implementation:
I chose to name my directive
selectso it will be applied to all select elements (alongside the native Angularselectdirective - yes that's possible). If you prefer to apply it to specific controls only, then rename it, restrict it to attributes (restrict: 'A') and add it as an attribute to your elements.Due (or thanks) to
require: '?ngModel', the control will be ignored if it is not bound to anngModel.Since our directive augments the
ngModelController.$render()method, which is defined by theselectdirective (executing at priority 0), we need to force our directive's link function to be executed after theselectdirective. Thus, it needs a higher priority, because "post-link functions are run in reverse [priority] order.".