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

Commit bcf67a5

Browse files
committed
fix(mdAutocomplete): Compile autocomplete template against proper scope.
After the performance modifications to make autocomplete use the virtual repeat directive, the autocomplete no longer compiled the contents of the dropdown against the proper parent scope This PR fixes it by manually compiling against the proper parent scope and copying over the necessary `item` and `$index` properties. Fixes #4390. Fixes #4495.
1 parent d7ffe17 commit bcf67a5

File tree

4 files changed

+77
-24
lines changed

4 files changed

+77
-24
lines changed

src/components/autocomplete/autocomplete.spec.js

+42
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,48 @@ describe('<md-autocomplete>', function () {
197197

198198
element.remove();
199199
}));
200+
201+
it('should compile the template against the parent scope', inject(function ($timeout) {
202+
var scope = createScope(null, { bang: 'boom' });
203+
var template = '\
204+
<md-autocomplete\
205+
md-selected-item="selectedItem"\
206+
md-search-text="searchText"\
207+
md-items="item in match(searchText)"\
208+
md-item-text="item.display"\
209+
placeholder="placeholder">\
210+
<md-item-template>\
211+
<span class="find-parent-scope">{{bang}}</span>\
212+
<span class="find-index">{{$index}}</span>\
213+
<span class="find-item">{{item.display}}</span>\
214+
</md-item-template>\
215+
</md-autocomplete>';
216+
var element = compile(template, scope);
217+
var ctrl = element.controller('mdAutocomplete');
218+
var ul = element.find('ul');
219+
220+
expect(scope.bang).toBe('boom');
221+
222+
element.scope().searchText = 'fo';
223+
224+
// Run our initial flush
225+
$timeout.flush();
226+
waitForVirtualRepeat(element);
227+
228+
// Wait for the next tick when the values will be updated
229+
$timeout.flush();
230+
231+
var li = ul.find('li')[0];
232+
233+
// Expect it to be compiled against the parent scope and have our variables copied
234+
expect(li.querySelector('.find-parent-scope').innerHTML).toBe('boom');
235+
expect(li.querySelector('.find-index').innerHTML).toBe('0');
236+
expect(li.querySelector('.find-item').innerHTML).toBe('foo');
237+
238+
$timeout.flush();
239+
240+
element.remove();
241+
}));
200242
});
201243

202244
describe('xss prevention', function () {

src/components/autocomplete/js/autocompleteDirective.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ function MdAutocomplete () {
187187
var templateTag = element.find('md-item-template').detach(),
188188
html = templateTag.length ? templateTag.html() : element.html();
189189
if (!templateTag.length) element.empty();
190-
return html;
190+
return '<md-autocomplete-parent-scope md-autocomplete-replace>' + html + '</md-autocomplete-parent-scope>';
191191
}
192192

193193
function getNoItemsTemplate() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
angular
2+
.module('material.components.autocomplete')
3+
.directive('mdAutocompleteParentScope', MdAutocompleteItemScopeDirective);
4+
5+
function MdAutocompleteItemScopeDirective($compile, $mdUtil) {
6+
return {
7+
restrict: 'AE',
8+
link: postLink,
9+
terminal: true
10+
};
11+
12+
function postLink(scope, element, attr) {
13+
var newScope = scope.$mdAutocompleteCtrl.parent.$new();
14+
var relevantVariables = ['item', '$index'];
15+
16+
// Watch for changes to our scope's variables and copy them to the new scope
17+
angular.forEach(relevantVariables, function(variable){
18+
scope.$watch(variable, function(value) {
19+
$mdUtil.nextTick(function() {
20+
newScope[variable] = value;
21+
});
22+
});
23+
});
24+
25+
// Recompile the contents with the new/modified scope
26+
$compile(element.contents())(newScope);
27+
28+
// Replace it if required
29+
if (attr.hasOwnProperty('mdAutocompleteReplace')) {
30+
element.after(element.contents());
31+
element.remove();
32+
}
33+
}
34+
}

src/components/autocomplete/js/parentScope.js

-23
This file was deleted.

0 commit comments

Comments
 (0)