X Tutup
Skip to content

Commit bd48c92

Browse files
divdavemmhevery
authored andcommitted
fix(ViewContainer) removeChild called with null parent
In view_container.js, templateElement.parentNode can be null when two template tags are nested in one another. Accessing the parent node through view.nodes[0].parentNode fixes the problem. closes angular#997 Closes angular#999
1 parent b61b8d6 commit bd48c92

File tree

3 files changed

+66
-3
lines changed

3 files changed

+66
-3
lines changed

modules/angular2/src/core/compiler/view_container.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ export class ViewContainer {
130130
var detachedView = this.get(atIndex);
131131
ListWrapper.removeAt(this._views, atIndex);
132132
if (isBlank(this._lightDom)) {
133-
ViewContainer.removeViewNodesFromParent(this.templateElement.parentNode, detachedView);
133+
ViewContainer.removeViewNodes(detachedView);
134134
} else {
135135
this._lightDom.redistribute();
136136
}
@@ -173,8 +173,11 @@ export class ViewContainer {
173173
}
174174
}
175175

176-
static removeViewNodesFromParent(parent, view) {
177-
for (var i = view.nodes.length - 1; i >= 0; --i) {
176+
static removeViewNodes(view) {
177+
var len = view.nodes.length;
178+
if (len == 0) return;
179+
var parent = view.nodes[0].parentNode;
180+
for (var i = len - 1; i >= 0; --i) {
178181
DOM.removeChild(parent, view.nodes[i]);
179182
}
180183
}

modules/angular2/test/directives/for_spec.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,31 @@ export function main() {
214214
cd.detectChanges();
215215
cd.detectChanges();
216216
expect(DOM.getText(view.nodes[0])).toEqual('a-2;b-2;|c-1;|');
217+
218+
component.items = [['e'], ['f', 'g']];
219+
cd.detectChanges();
220+
expect(DOM.getText(view.nodes[0])).toEqual('e-1;|f-2;g-2;|');
221+
222+
async.done();
223+
});
224+
}));
225+
226+
it('should repeat over nested arrays with no intermediate element', inject([AsyncTestCompleter], (async) => {
227+
compileWithTemplate(
228+
'<div><template [for] #item [of]="items">' +
229+
'<div template="for #subitem of item">' +
230+
'{{subitem}}-{{item.length}};' +
231+
'</div></template></div>'
232+
).then((pv) => {
233+
createView(pv);
234+
235+
component.items = [['a', 'b'], ['c']];
236+
cd.detectChanges();
237+
expect(DOM.getText(view.nodes[0])).toEqual('a-2;b-2;c-1;');
238+
239+
component.items = [['e'], ['f', 'g']];
240+
cd.detectChanges();
241+
expect(DOM.getText(view.nodes[0])).toEqual('e-1;f-2;g-2;');
217242
async.done();
218243
});
219244
}));

modules/angular2/test/directives/if_spec.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,39 @@ export function main() {
116116
});
117117
}));
118118

119+
it('should handle nested if correctly', inject([AsyncTestCompleter], (async) => {
120+
compileWithTemplate('<div><template [if]="booleanCondition"><copy-me *if="nestedBooleanCondition">hello</copy-me></template></div>').then((pv) => {
121+
createView(pv);
122+
123+
component.booleanCondition = false;
124+
cd.detectChanges();
125+
expect(DOM.querySelectorAll(view.nodes[0], 'copy-me').length).toEqual(0);
126+
expect(DOM.getText(view.nodes[0])).toEqual('');
127+
128+
component.booleanCondition = true;
129+
cd.detectChanges();
130+
expect(DOM.querySelectorAll(view.nodes[0], 'copy-me').length).toEqual(1);
131+
expect(DOM.getText(view.nodes[0])).toEqual('hello');
132+
133+
component.nestedBooleanCondition = false;
134+
cd.detectChanges();
135+
expect(DOM.querySelectorAll(view.nodes[0], 'copy-me').length).toEqual(0);
136+
expect(DOM.getText(view.nodes[0])).toEqual('');
137+
138+
component.nestedBooleanCondition = true;
139+
cd.detectChanges();
140+
expect(DOM.querySelectorAll(view.nodes[0], 'copy-me').length).toEqual(1);
141+
expect(DOM.getText(view.nodes[0])).toEqual('hello');
142+
143+
component.booleanCondition = false;
144+
cd.detectChanges();
145+
expect(DOM.querySelectorAll(view.nodes[0], 'copy-me').length).toEqual(0);
146+
expect(DOM.getText(view.nodes[0])).toEqual('');
147+
148+
async.done();
149+
});
150+
}));
151+
119152
it('should update several nodes with if', inject([AsyncTestCompleter], (async) => {
120153
var templateString =
121154
'<div>' +
@@ -195,11 +228,13 @@ export function main() {
195228
@Component({selector: 'test-cmp'})
196229
class TestComponent {
197230
booleanCondition: boolean;
231+
nestedBooleanCondition: boolean;
198232
numberCondition: number;
199233
stringCondition: string;
200234
functionCondition: Function;
201235
constructor() {
202236
this.booleanCondition = true;
237+
this.nestedBooleanCondition = true;
203238
this.numberCondition = 1;
204239
this.stringCondition = "foo";
205240
this.functionCondition = function(s, n){

0 commit comments

Comments
 (0)
X Tutup