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

fix(select): use $viewValue instead of $modelValue #8937

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions src/ng/directive/select.js
Original file line number Diff line number Diff line change
Expand Up @@ -436,16 +436,16 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
function getSelectedSet() {
var selectedSet = false;
if (multiple) {
var modelValue = ctrl.$modelValue;
if (trackFn && isArray(modelValue)) {
var viewValue = ctrl.$viewValue;
if (trackFn && isArray(viewValue)) {
selectedSet = new HashMap([]);
var locals = {};
for (var trackIndex = 0; trackIndex < modelValue.length; trackIndex++) {
locals[valueName] = modelValue[trackIndex];
selectedSet.put(trackFn(scope, locals), modelValue[trackIndex]);
for (var trackIndex = 0; trackIndex < viewValue.length; trackIndex++) {
locals[valueName] = viewValue[trackIndex];
selectedSet.put(trackFn(scope, locals), viewValue[trackIndex]);
}
} else {
selectedSet = new HashMap(modelValue);
selectedSet = new HashMap(viewValue);
}
}
return selectedSet;
Expand All @@ -470,7 +470,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
optionGroup,
option,
existingParent, existingOptions, existingOption,
modelValue = ctrl.$modelValue,
viewValue = ctrl.$viewValue,
values = valuesFn(scope) || [],
keys = keyName ? sortedKeys(values) : values,
key,
Expand Down Expand Up @@ -508,10 +508,10 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
} else {
if (trackFn) {
var modelCast = {};
modelCast[valueName] = modelValue;
modelCast[valueName] = viewValue;
selected = trackFn(scope, modelCast) === trackFn(scope, locals);
} else {
selected = modelValue === valueFn(scope, locals);
selected = viewValue === valueFn(scope, locals);
}
selectedSet = selectedSet || selected; // see if at least one item is selected
}
Expand All @@ -527,7 +527,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
});
}
if (!multiple) {
if (nullOption || modelValue === null) {
if (nullOption || viewValue === null) {
// insert null option if we have a placeholder, or the model is null
optionGroups[''].unshift({id:'', label:'', selected:!selectedSet});
} else if (!selectedSet) {
Expand Down
124 changes: 124 additions & 0 deletions test/ng/directive/selectSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1550,6 +1550,130 @@ describe('select', function() {
expect(scope.value).toBe(false);
});
});

describe('ngModelCtrl', function() {
it('should prefix the model value with the word "the" using $parsers', function() {
createSelect({
'name': 'select',
'ng-model': 'value',
'ng-options': 'item for item in [\'first\', \'second\', \'third\', \'fourth\']',
});

scope.form.select.$parsers.push(function(value) {
return 'the ' + value;
});

element.val('2');
browserTrigger(element, 'change');
expect(scope.value).toBe('the third');
expect(element.val()).toBe('2');
});

it('should prefix the view value with the word "the" using $formatters', function() {
createSelect({
'name': 'select',
'ng-model': 'value',
'ng-options': 'item for item in [\'the first\', \'the second\', \'the third\', \'the fourth\']',
});

scope.form.select.$formatters.push(function(value) {
return 'the ' + value;
});

scope.$apply(function() {
scope.value = 'third';
});
expect(element.val()).toBe('2');
});

it('should fail validation when $validators fail', function() {
createSelect({
'name': 'select',
'ng-model': 'value',
'ng-options': 'item for item in [\'first\', \'second\', \'third\', \'fourth\']',
});

scope.form.select.$validators.fail = function() {
return false;
};

element.val('2');
browserTrigger(element, 'change');
expect(element).toBeInvalid();
expect(scope.value).toBeUndefined();
expect(element.val()).toBe('2');
});

it('should pass validation when $validators pass', function() {
createSelect({
'name': 'select',
'ng-model': 'value',
'ng-options': 'item for item in [\'first\', \'second\', \'third\', \'fourth\']',
});

scope.form.select.$validators.pass = function() {
return true;
};

element.val('2');
browserTrigger(element, 'change');
expect(element).toBeValid();
expect(scope.value).toBe('third');
expect(element.val()).toBe('2');
});

it('should fail validation when $asyncValidators fail', inject(function($q, $rootScope) {
var defer;
createSelect({
'name': 'select',
'ng-model': 'value',
'ng-options': 'item for item in [\'first\', \'second\', \'third\', \'fourth\']',
});

scope.form.select.$asyncValidators.async = function() {
defer = $q.defer();
return defer.promise;
};

element.val('2');
browserTrigger(element, 'change');
expect(scope.form.select.$pending).toBeDefined();
expect(scope.value).toBeUndefined();
expect(element.val()).toBe('2');

defer.reject();
$rootScope.$digest();
expect(scope.form.select.$pending).toBeUndefined();
expect(scope.value).toBeUndefined();
expect(element.val()).toBe('2');
}));

it('should pass validation when $asyncValidators pass', inject(function($q, $rootScope) {
var defer;
createSelect({
'name': 'select',
'ng-model': 'value',
'ng-options': 'item for item in [\'first\', \'second\', \'third\', \'fourth\']',
});

scope.form.select.$asyncValidators.async = function() {
defer = $q.defer();
return defer.promise;
};

element.val('2');
browserTrigger(element, 'change');
expect(scope.form.select.$pending).toBeDefined();
expect(scope.value).toBeUndefined();
expect(element.val()).toBe('2');

defer.resolve();
$rootScope.$digest();
expect(scope.form.select.$pending).toBeUndefined();
expect(scope.value).toBe('third');
expect(element.val()).toBe('2');
}));
});
});


Expand Down