Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix(ngRequired): set valid to false if select value is required (value is not in options) #13354

Closed
wants to merge 5 commits into from
Closed
44 changes: 37 additions & 7 deletions src/ng/directive/ngOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,34 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
selectValueMap[selectValue] = optionItem;
}

/**
*
* @returns {boolean}
*/
function isSelectedOptionValid() {

var selectedValue = selectElement.val();

if (!selectedValue) {
return false;
}

// in case select is multiple then check
// if one of the selected values matched with the options return true
// or return false if no value match
if (isArray(selectedValue)) {
for (var i = 0, length = selectedValue.length; i < length; i++) {
if (selectValueMap[selectedValue[i]]) {
return true;
}
}
return false;
}

return !!selectValueMap[selectedValue];

}

return {
items: optionItems,
selectValueMap: selectValueMap,
Expand All @@ -397,7 +425,9 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
// If the viewValue could be an object that may be mutated by the application,
// we need to make a copy and not return the reference to the value on the option.
return trackBy ? angular.copy(option.viewValue) : option.viewValue;
}
},

isSelectedOptionValid: isSelectedOptionValid
};
}
};
Expand Down Expand Up @@ -510,11 +540,6 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {

} else {

ngModelCtrl.$isEmpty = function(value) {
return !value || value.length === 0;
};


selectCtrl.writeValue = function writeNgOptionsMultiple(value) {
options.items.forEach(function(option) {
option.element.selected = false;
Expand Down Expand Up @@ -557,7 +582,12 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {

}
}
// Copy the implementation of $isEmpty function to be used in overwritten one
var $$isEmpty = ngModelCtrl.$isEmpty;

ngModelCtrl.$isEmpty = function(value) {
return $$isEmpty(value) || !options.isSelectedOptionValid();
};

if (providedEmptyOption) {

Expand Down Expand Up @@ -731,7 +761,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
ngModelCtrl.$render();

// Check to see if the value has changed due to the update to the options
if (!ngModelCtrl.$isEmpty(previousValue)) {
if (!$$isEmpty(previousValue)) {
var nextValue = selectCtrl.readValue();
var isNotPrimitive = ngOptions.trackBy || multiple;
if (isNotPrimitive ? !equals(previousValue, nextValue) : previousValue !== nextValue) {
Expand Down