From b6fb9c356620775c074a2f04be880c7c7472b788 Mon Sep 17 00:00:00 2001 From: robw Date: Tue, 8 Dec 2015 15:38:50 -0800 Subject: [PATCH 1/3] feat(ngOptions): add ngEmptyValue attribute to ngOptions allow an optional ng-empty-value attribute on select elements using ng-options. any option whose value is an empty string will be replaced with the given empty-value. Closes: #13334 --- src/ng/directive/ngOptions.js | 9 +++++++++ test/ng/directive/ngOptionsSpec.js | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/ng/directive/ngOptions.js b/src/ng/directive/ngOptions.js index 7f1e13ec32f4..f2a849afe163 100644 --- a/src/ng/directive/ngOptions.js +++ b/src/ng/directive/ngOptions.js @@ -31,6 +31,9 @@ var ngOptionsMinErr = minErr('ngOptions'); * be nested into the `' + + '' + + ''; + compile(html); + scope.$apply(function() { + scope.choices = ['A','B','C']; + scope.someModel = ""; + scope.someVar = "foo"; + }); + //current implementation only works if select is not pristine, so we click it back and forth + setSelectValue(element, 3); + setSelectValue(element, 0); + + //make sure the empty value is being evaluated as an Angular expression + expect(scope.someModel).toBe("foo"); + + dealoc(element); + + }); it('should be possible to use ngIf in the blank option', function() { var option; From df89869cb26302ad9cb043166b8097ef5c6eea5b Mon Sep 17 00:00:00 2001 From: robw Date: Tue, 15 Dec 2015 14:22:27 -0800 Subject: [PATCH 2/3] changes in response to notes in PR thread -- to be squashed later --- src/ng/directive/ngOptions.js | 4 +++- test/ng/directive/ngOptionsSpec.js | 24 +++++++++++++++++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/ng/directive/ngOptions.js b/src/ng/directive/ngOptions.js index f2a849afe163..410051f50ca4 100644 --- a/src/ng/directive/ngOptions.js +++ b/src/ng/directive/ngOptions.js @@ -493,10 +493,12 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { } }; + var emptyValueParseFn = 'ngEmptyValue' in attr && attr.ngEmptyValue.length > 0 && $parse(attr.ngEmptyValue); + selectCtrl.readValue = function readNgOptionsValue() { // Allow a default value to be substituted for any options with empty values - if (selectElement.val() === '') return $parse(attr.ngEmptyValue)(scope); + if (selectElement.val() === '' && emptyValueParseFn) return emptyValueParseFn(scope); var selectedOption = options.selectValueMap[selectElement.val()]; diff --git a/test/ng/directive/ngOptionsSpec.js b/test/ng/directive/ngOptionsSpec.js index b9c00895f2ff..0d1ec1663d4a 100644 --- a/test/ng/directive/ngOptionsSpec.js +++ b/test/ng/directive/ngOptionsSpec.js @@ -2144,13 +2144,15 @@ describe('ngOptions', function() { }); it('should be possible to specify a value for empty options', function() { - var html = ''; - compile(html); + createSelect({ + 'ng-model':'selected', + 'ng-empty-value': 'someVar', + 'ng-options':'c for c in choices' + }, true); + scope.$apply(function() { scope.choices = ['A','B','C']; - scope.someModel = ""; + scope.selected = ""; scope.someVar = "foo"; }); //current implementation only works if select is not pristine, so we click it back and forth @@ -2158,9 +2160,17 @@ describe('ngOptions', function() { setSelectValue(element, 0); //make sure the empty value is being evaluated as an Angular expression - expect(scope.someModel).toBe("foo"); + expect(scope.selected).toBe("foo"); - dealoc(element); + //make sure a change to the value given in ng-empty-value also changes the model + scope.$apply(function() { + scope.someVar = "bar"; + }); + + setSelectValue(element, 3); + setSelectValue(element, 0); + + expect(scope.selected).toBe("bar"); }); From 0a5306166652c80a2af932e27f7939f397441889 Mon Sep 17 00:00:00 2001 From: robw Date: Tue, 15 Dec 2015 14:42:37 -0800 Subject: [PATCH 3/3] split line for linter --- src/ng/directive/ngOptions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ng/directive/ngOptions.js b/src/ng/directive/ngOptions.js index 410051f50ca4..b5ce45475b02 100644 --- a/src/ng/directive/ngOptions.js +++ b/src/ng/directive/ngOptions.js @@ -493,7 +493,8 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) { } }; - var emptyValueParseFn = 'ngEmptyValue' in attr && attr.ngEmptyValue.length > 0 && $parse(attr.ngEmptyValue); + var emptyValueParseFn = 'ngEmptyValue' in attr && attr.ngEmptyValue.length > 0 + && $parse(attr.ngEmptyValue); selectCtrl.readValue = function readNgOptionsValue() {