I am a little confused why ngAfterContentInit executes twice in this scenario. I created a stripped down version of our application to reproduce the error. In short, I use *contentItem for component tags, which are then processed by the standard-layout component for rendering. As soon as I follow this pattern, demo ngAfterContentInit is executed twice.
I posted a demo application on github that will reproduce the error: https://github.com/jVaaS/stackoverflow/tree/master/ngaftercontentinit
Otherwise, these are the important bits:
buggy-app.dart:
@Component( selector: "buggy-app", template: """ <standard-layout> <demo *contentItem></demo> </standard-layout> """, directives: const [ ContentItemDirective, StandardLayout, Demo ] ) class BuggyApp implements AfterContentInit { @override ngAfterContentInit() { print(">>> ngAfterContentInit: BuggyApp"); } }
Standard-layout.dart:
//////////////////////////////////////////////////////////////////////////////// /// /// Standard Layout Component /// <standard-layout></standard-layout> /// @Component( selector: "standard-layout", template: """ <div *ngFor="let item of contentItems ?? []"> <template [ngTemplateOutlet]="item.template"></template> </div> """, directives: const [ROUTER_DIRECTIVES, ContentItem]) class StandardLayout implements AfterContentInit { @ContentChildren(ContentItemDirective) QueryList<ContentItemDirective> contentItems; @override ngAfterContentInit() { print(">>> ngAfterContentInit: StandardLayout"); } } //////////////////////////////////////////////////////////////////////////////// /// /// Content Item Directive /// *contentItem /// @Directive(selector: '[contentItem]') class ContentItemDirective implements AfterContentInit { final ViewContainerRef vcRef; final TemplateRef template; final ComponentResolver componentResolver; ContentItemDirective(this.vcRef, this.template, this.componentResolver); ComponentRef componentRef; @override ngAfterContentInit() async { final componentFactory = await componentResolver.resolveComponent(ContentItem); componentRef = vcRef.createComponent(componentFactory); (componentRef.instance as ContentItem) ..template = template; } } //////////////////////////////////////////////////////////////////////////////// /// /// Content Item Generator /// @Component( selector: "content-item", host: const { '[class.content-item]': "true", }, template: """ <template [ngTemplateOutlet]="template"></template> """, directives: const [NgTemplateOutlet] ) class ContentItem { TemplateRef template; } ////////////////////////////////////////////////////////////////////////////////
and finally demo.dart :
@Component( selector: "demo", template: "Hello World Once, but demo prints twice!") class Demo implements AfterContentInit { @override ngAfterContentInit() { print(">>> ngAfterContentInit: Demo"); } }
main.dart there is not much in it:
void main() { bootstrap(BuggyApp); }
When I ran this, Hello World prints once as expected: 
but when viewing the terminal:

Thus, the demo component displays exactly once, but its ngAfterContentInit runs twice, which causes chaos when your assumption is that it runs only once.
I tried adding a hacky workaround, but it seems that the component does receive the re-render twice:
int counter = 0; @override ngAfterContentInit() { if (counter == 0) { print(">>> ngAfterContentInit: Demo"); counter++; } }
Is this a bug in Angular or is there something I can do to prevent this?
pubspec.yaml if necessary:
name: bugdemo version: 0.0.0 description: Bug Demo environment: sdk: '>=1.13.0 <2.0.0' dependencies: angular2: 3.1.0 browser: ^0.10.0 http: any js: ^0.6.0 dart_to_js_script_rewriter: ^1.0.1 transformers: - angular2: platform_directives: - package:angular2/common.dart
and index.html for a good measure:
<!DOCTYPE html> <html> <head> <title>Strange Bug</title> </head> <body> <buggy-app> Loading ... </buggy-app> <script async src="main.dart" type="application/dart"></script> <script async src="packages/browser/dart.js"></script> </body> </html>
Update
Therefore, it has been suggested that this may be the case that this only happens twice in dev-mode. I did pub build and ran index.html , which now contains main.dart.js in regular Chrome.

It still runs twice, tried using ngAfterViewInit , and this also runs twice.
Logged Error: https://github.com/dart-lang/angular/issues/478