Navigation Menu

Skip to content

Commit

Permalink
fix(compiler): don't trigger duplicated directives
Browse files Browse the repository at this point in the history
Fixes #2756
Closes #2568
  • Loading branch information
pkozlowski-opensource authored and tbosch committed Jul 1, 2015
1 parent 0b50258 commit 0598226
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 2 deletions.
10 changes: 8 additions & 2 deletions modules/angular2/src/core/compiler/compiler.ts
Expand Up @@ -153,8 +153,8 @@ export class Compiler {
}
}

var boundDirectives =
ListWrapper.map(directives, (directive) => this._bindDirective(directive));
var boundDirectives = this._removeDuplicatedDirectives(
ListWrapper.map(directives, (directive) => this._bindDirective(directive)));

var renderTemplate = this._buildRenderTemplate(component, view, boundDirectives);
pvPromise =
Expand All @@ -167,6 +167,12 @@ export class Compiler {
return pvPromise;
}

private _removeDuplicatedDirectives(directives: List<DirectiveBinding>): List<DirectiveBinding> {
var directivesMap: Map<number, DirectiveBinding> = new Map();
directives.forEach((dirBinding) => { directivesMap.set(dirBinding.key.id, dirBinding); });
return MapWrapper.values(directivesMap);
}

private _compileNestedProtoViews(componentBinding, renderPv, directives): Promise<AppProtoView>|
AppProtoView {
var protoViews =
Expand Down
48 changes: 48 additions & 0 deletions modules/angular2/test/core/compiler/integration_spec.ts
Expand Up @@ -299,6 +299,40 @@ export function main() {
.then((rootTC) => { async.done(); });
}));

it('should execute a given directive once, even if specified multiple times',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new viewAnn.View({
template: '<p no-duplicate></p>',
directives: [
DuplicateDir,
DuplicateDir,
[DuplicateDir, [DuplicateDir, bind(DuplicateDir).toClass(DuplicateDir)]]
]
}))
.createAsync(MyComp)
.then((rootTC) => {
expect(rootTC.nativeElement).toHaveText('noduplicate');
async.done();
});
}));

it('should use the last directive binding per directive',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new viewAnn.View({
template: '<p no-duplicate></p>',
directives: [
bind(DuplicateDir)
.toClass(DuplicateDir),
bind(DuplicateDir).toClass(OtherDuplicateDir)
]
}))
.createAsync(MyComp)
.then((rootTC) => {
expect(rootTC.nativeElement).toHaveText('othernoduplicate');
async.done();
});
}));

it('should support directives where a selector matches property binding',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new viewAnn.View(
Expand Down Expand Up @@ -1805,3 +1839,17 @@ class ExportDir {
@Component({selector: 'comp'})
class ComponentWithoutView {
}

@Directive({selector: '[no-duplicate]'})
class DuplicateDir {
constructor(renderer: DomRenderer, private elRef: ElementRef) {
DOM.setText(elRef.nativeElement, DOM.getText(elRef.nativeElement) + 'noduplicate');
}
}

@Directive({selector: '[no-duplicate]'})
class OtherDuplicateDir {
constructor(renderer: DomRenderer, private elRef: ElementRef) {
DOM.setText(elRef.nativeElement, DOM.getText(elRef.nativeElement) + 'othernoduplicate');
}
}

0 comments on commit 0598226

Please sign in to comment.