2

With the following code:

template

<button (click)="myMethod()">myMethod()</button>
<!-- <button (click)="foo()">foo()</button> -->

<ng-container [ngSwitch]="state">
  <ng-container *ngSwitchCase="0">
    <div></div>
    <button (click)="myMethod()">myMethod()</button>
    <button (click)="foo()">foo()</button><!-- why no error -->
  </ng-container>
  <div *ngSwitchCase="1"></div>
</ng-container>

component

export class MyComponent {

  public state = 0;

  public myMethod(): void {
    // no op
  }

}

ng build --aot builds, but if you uncomment the 2nd line in the template you expectedly get

Property 'foo' does not exist on type 'MyComponent'.

Why does the <button (click)="foo()">foo()</button> inside the ng-container not error?

Before you suggest:

<div *ngSwitchCase="0">
  <div></div>
  <button (click)="myMethod()">myMethod()</button>
  <button (click)="foo()">foo()</button><!-- why no error -->
</div>

that will render as

<div>
  <div></div>
  <button>myMethod()</button>
  <button>foo()</button>
</div>

but I need just

<div></div>
<button>myMethod()</button>
<button>foo()</button>

And there are other ways around this, but the question is for fundamental understanding before making bug or feat.

Wilhelmina Lohan
  • 2,803
  • 2
  • 29
  • 58
  • I think this might be related to https://github.com/angular/angular/issues/19792 – Wilhelmina Lohan Jan 04 '19 at 19:01
  • AoT compiles the template beforehand, and is looking for the bindings to be generated. On the other hand, having it in an ng-container is a particular thing, since the ng-container will not be interpreted and thus compiled until it is called. See this article : https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet – Alex Beugnet Jan 04 '19 at 19:04
  • Ahh so `ng-container` is not compiled at build time? If thats so, I'll accept that answer. – Wilhelmina Lohan Jan 04 '19 at 19:07

2 Answers2

2

"Are there any other ways around this...?"

Have you tried this: https://angular.io/guide/aot-compiler#fulltemplatetypecheck ?

It looks like this AOT setting is (currently) inactive by default.

Bonus:

Also see this section at compiler github on binding expressions: https://github.com/angular/angular/blob/master/aio/content/guide/aot-compiler.md#phase-3-binding-expression-validation

The validation uses the TypeScript type checker and the options supplied to the TypeScript compiler to control how detailed the type validation is

The error 'Property X does not exist on type Y' is thrown at this phase, and the level of validation detail is adjustable via compiler parameters, such as the aforementioned parameter 'fulltemplatetypecheck'.

Keenan Diggs
  • 2,287
  • 16
  • 17
  • Please let me know if this solves the problem you are experiencing. – Keenan Diggs Jan 04 '19 at 20:03
  • Not sure how to set `fullTemplateTypeCheck` in angular cli project. https://github.com/angular/angular-cli/issues/12444#issuecomment-426352896 seems to imply it is already set to true on aot build. – Wilhelmina Lohan Jan 04 '19 at 21:01
  • Throws `Unknown compiler option 'angularCompilerOptions'.` if you set it in `tsconfig.json` but seems to work in `tsconfig.app.json`, just afraid to set `angularCompilerOptions` with all on the automagical stuff cli does – Wilhelmina Lohan Jan 04 '19 at 21:06
  • I don't think you should be afraid of the fulltemplatetypecheck paramter. The docs specifically say it will be `true` by default in the future. https://angular.io/guide/aot-compiler#fulltemplatetypecheck It is my guess that this parameter was set to `false` by the dev team earlier in the life of the compiler for performance reasons. – Keenan Diggs Jan 04 '19 at 21:09
  • I mean, by default `angularCompilerOptions` isn't even a part of `tsconfig.app.json` in a cli project. Setting it with one property for `fulltemplatetypecheck` works on simple duplication repo but how can I be confident that setting `angularCompilerOptions` won't overwrite any of the other compiler options or change the behavior of angular cli in unforeseen ways later on down the line or in a large production project. (been bitten by doing stuff like this in angular cli before) – Wilhelmina Lohan Jan 04 '19 at 21:43
  • Perhaps knowledge is power. You might feel better if you had a more in-depth understanding of the AOT compiler and how Angular uses tsconfig. If you want, you could do a comprehensive reading of the respective doc entries. https://angular.io/guide/typescript-configuration (tsconfig) https://angular.io/guide/file-structure#default-app-project-files (tsconfig.app.json) https://angular.io/guide/aot-compiler (AOT) – Keenan Diggs Jan 04 '19 at 22:05
  • Its angular cli specifically I'm worried about. ie my `tsconfig.app.json` is not equal to what ngc gets – Wilhelmina Lohan Jan 04 '19 at 22:23
  • I'm over thinking though – Wilhelmina Lohan Jan 04 '19 at 22:33
1

This was my comment :

AoT compiles the template beforehand, and is looking for the bindings to be generated. On the other hand, having it in an ng-container is a particular thing, since the ng-container will not be interpreted and thus compiled until it is called.

See this article :

https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/


I tried searching more info into it, and I just went back to your first comment about the Angular issue :

From this thread https://github.com/angular/angular/issues/20287 to this issue linked : https://github.com/angular/angular/issues/19792.

It seems to be an on-going bug, so that means that ng-containers are supposed to be compiled. I guess there is nothing you can do about it for now !

Alex Beugnet
  • 4,003
  • 4
  • 23
  • 40