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

Commit ca51125

Browse files
committed
fix(ngOptions): unset the select.ngModelCtrl when ngOptions is present
1 parent c38f876 commit ca51125

File tree

3 files changed

+78
-15
lines changed

3 files changed

+78
-15
lines changed

src/ng/directive/ngOptions.js

+12-7
Original file line numberDiff line numberDiff line change
@@ -392,11 +392,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
392392
var optionTemplate = document.createElement('option'),
393393
optGroupTemplate = document.createElement('optgroup');
394394

395-
return {
396-
restrict: 'A',
397-
terminal: true,
398-
require: ['select', 'ngModel'],
399-
link: function(scope, selectElement, attr, ctrls) {
395+
function ngOptionsPostLink(scope, selectElement, attr, ctrls) {
400396

401397
var selectCtrl = ctrls[0];
402398
var ngModelCtrl = ctrls[1];
@@ -448,12 +444,11 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
448444
unknownOption.remove();
449445
};
450446

451-
452447
// Update the controller methods for multiple selectable options
453448
if (!multiple) {
454449

455450
selectCtrl.writeValue = function writeNgOptionsValue(value) {
456-
var option = options && options.getOptionFromViewValue(value);
451+
var option = options.getOptionFromViewValue(value);
457452

458453
if (option && !option.disabled) {
459454
if (selectElement[0].value !== option.selectValue) {
@@ -726,7 +721,17 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
726721
}
727722

728723
}
724+
}
729725

726+
return {
727+
restrict: 'A',
728+
terminal: true,
729+
require: ['select', 'ngModel'],
730+
link: {
731+
pre: function ngOptionsPreLink(scope, selectElement, attr, ctrls) {
732+
ctrls[0].ngModelCtrl = null;
733+
},
734+
post: ngOptionsPostLink
730735
}
731736
};
732737
}];

src/ng/directive/select.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,13 @@ var selectDirective = function() {
308308
restrict: 'E',
309309
require: ['select', '?ngModel'],
310310
controller: SelectController,
311-
link: function(scope, element, attr, ctrls) {
311+
priority: 1,
312+
link: {
313+
pre: selectPreLink
314+
}
315+
};
316+
317+
function selectPreLink(scope, element, attr, ctrls) {
312318

313319
// if ngModel is not defined, we don't need to do anything
314320
var ngModelCtrl = ctrls[1];
@@ -378,7 +384,6 @@ var selectDirective = function() {
378384

379385
}
380386
}
381-
};
382387
};
383388

384389

test/ng/directive/ngOptionsSpec.js

+59-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
describe('ngOptions', function() {
44

5-
var scope, formElement, element, $compile;
5+
var scope, formElement, element, $compile, linkLog;
66

77
function compile(html) {
88
formElement = jqLite('<form name="form">' + html + '</form>');
@@ -104,15 +104,51 @@ describe('ngOptions', function() {
104104
});
105105
});
106106

107-
beforeEach(module(function($compileProvider) {
107+
beforeEach(module(function($compileProvider, $provide) {
108+
linkLog = [];
109+
108110
$compileProvider
109-
.directive('compileContents', function($compile) {
111+
.directive('customSelect', function() {
110112
return {
111-
link: function(scope, element) {
113+
restrict: "E",
114+
replace: true,
115+
scope: {
116+
ngModel: '=',
117+
options: '='
118+
},
119+
templateUrl: 'select_template.html',
120+
link: function(scope, $element, attributes) {
121+
scope.selectable_options = scope.options;
122+
}
123+
};
124+
})
125+
126+
.directive('oCompileContents', function() {
127+
return {
128+
link: function(scope, element) {
129+
linkLog.push('linkCompileContents');
112130
$compile(element.contents())(scope);
113131
}
114132
};
115133
});
134+
135+
$provide.decorator('ngOptionsDirective', function($delegate) {
136+
137+
var origPreLink = $delegate[0].link.pre;
138+
var origPostLink = $delegate[0].link.post;
139+
140+
$delegate[0].compile = function() {
141+
return {
142+
pre: origPreLink,
143+
post: function() {
144+
linkLog.push('linkNgOptions');
145+
origPostLink.apply(this, arguments);
146+
}
147+
};
148+
};
149+
150+
return $delegate;
151+
});
116152
}));
117153

118154
beforeEach(inject(function($rootScope, _$compile_) {
@@ -2135,13 +2171,30 @@ describe('ngOptions', function() {
21352171
it('should not throw when a directive compiles the blank option before ngOptions is linked', function() {
21362172
expect(function() {
21372173
createSelect({
2138-
'compile-contents': '',
2174+
'o-compile-contents': '',
21392175
'name': 'select',
21402176
'ng-model': 'value',
2141-
'ng-options': 'item for item in items',
2177+
'ng-options': 'item for item in items'
21422178
}, true);
21432179
}).not.toThrow();
2180+
2181+
expect(linkLog).toEqual(['linkCompileContents', 'linkNgOptions']);
21442182
});
2183+
2184+
2185+
it('should not throw with a directive that replaces', inject(function($templateCache, $httpBackend) {
2186+
$templateCache.put('select_template.html', '<select ng-options="option as option for option in selectable_options"> <option value="">This is a test</option> </select>');
2187+
2188+
scope.options = ['a', 'b', 'c', 'd'];
2189+
2190+
expect(function() {
2191+
var element = $compile('<custom-select ng-model="value" options="options"></custom-select>')(scope);
2192+
scope.$digest();
2193+
dealoc(element);
2194+
}).not.toThrow();
2195+
2196+
}));
2197+
21452198
});
21462199

21472200

0 commit comments

Comments
 (0)