Skip to content

Commit c38f876

Browse files
committed
fix(ngOptions): don't throw if options are unset inside writeValue
This can happen in the following case: - there's a blank option inside the select - another directive on the select element compiles the contents of it before ngOptions is linked. Now this happens: - the option directive is compiled and adds an element $destroy listener that calls ngModel.$render - when ngOptions processes the blank option, it removes the element, and triggers the $destroy listener - ngModel.$render delegates to selectCtrl.writeValue, which accesses the options - in that phase, the options aren't yet set Fixes angular#11685
1 parent e51174b commit c38f876

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

src/ng/directive/ngOptions.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
453453
if (!multiple) {
454454

455455
selectCtrl.writeValue = function writeNgOptionsValue(value) {
456-
var option = options.getOptionFromViewValue(value);
456+
var option = options && options.getOptionFromViewValue(value);
457457

458458
if (option && !option.disabled) {
459459
if (selectElement[0].value !== option.selectValue) {

test/ng/directive/ngOptionsSpec.js

+23
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,17 @@ describe('ngOptions', function() {
104104
});
105105
});
106106

107+
beforeEach(module(function($compileProvider) {
108+
$compileProvider
109+
.directive('compileContents', function($compile) {
110+
return {
111+
link: function(scope, element) {
112+
$compile(element.contents())(scope);
113+
}
114+
};
115+
});
116+
}));
117+
107118
beforeEach(inject(function($rootScope, _$compile_) {
108119
scope = $rootScope.$new(); //create a child scope because the root scope can't be $destroy-ed
109120
$compile = _$compile_;
@@ -2119,6 +2130,18 @@ describe('ngOptions', function() {
21192130
option = element.find('option').eq(0);
21202131
expect(option.text()).toBe('A');
21212132
});
2133+
2134+
2135+
it('should not throw when a directive compiles the blank option before ngOptions is linked', function() {
2136+
expect(function() {
2137+
createSelect({
2138+
'compile-contents': '',
2139+
'name': 'select',
2140+
'ng-model': 'value',
2141+
'ng-options': 'item for item in items',
2142+
}, true);
2143+
}).not.toThrow();
2144+
});
21222145
});
21232146

21242147

0 commit comments

Comments
 (0)