angular: ES6 template literal expressions not working past v9

🐞 bug report

Is this a regression?

Yes, the previous version in which this bug was not present was: ^8

Description

Using a template literal expression used to work until Angular 9, for as long as the template lived in the TS source not in HTML (obviously).

Since Angular 9 that does not work any longer in one scenario. I am mostly focusing on library builds here:

Working

  • build library with Angular 9 Ivy & serve the Angular 9 application
  • build library with Angular 8 View Engine & serve the Angular 8 application
  • build library with Angular 8 View Engine & serve the Angular 9 application (ngcc)

Not working

  • build library with Angular 9 View Engine (ng build lib --prod) & serve the Angular 9 application (ngcc)

🔬 Minimal Reproduction

In any Angular workspace create a library and do the following:

const enum Demo {
  First
}

@Component({
  template: `
    Static variable: ${ Demo.First  }
  `
})
export class DemoComponent {}

🔥 Exception or Error

error NG1010: template must be a string

🌍 Your Environment

Angular Version:

Angular CLI: 9.0.3
Node: 12.15.0
OS: darwin x64

Angular: 9.0.2
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.900.3
@angular-devkit/build-angular      0.900.3
@angular-devkit/build-ng-packagr   0.900.3
@angular-devkit/build-optimizer    0.900.3
@angular-devkit/build-webpack      0.900.3
@angular-devkit/core               9.0.3
@angular-devkit/schematics         9.0.3
@angular/cdk                       9.0.1
@angular/cli                       9.0.3
@angular/material                  9.0.1
@ngtools/webpack                   9.0.3
@schematics/angular                9.0.3
@schematics/update                 0.900.3
ng-packagr                         9.0.1
rxjs                               6.5.4
typescript                         3.7.5
webpack                            4.41.2

Anything else relevant?

I am not 100% sure this was ever officially supported, even though I would have hoped so, since it is native ES6 feature. If it wasn’t supported, please close the issue.

Interesting observation is, that View Engine compiled library from Angular 8 is correctly processed by ngcc, while View Engine from Angular 9 surprisingly fails.


EDIT: Seems like an easy reproduction mentioned above is not reproducible any more. I can still reproduce it, if I use literal expressions while binding to input, e.g.: [title]="${variable}".

Reproduction:

Resulting in error:

dist/example/fesm2015/example.js:29:19 - error NG1010: template must be a string

29         template: `
                     ~
30     <button [title]="${ButtonType.Button}">Button</button>
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31   `
   ~~~
dist/example/fesm2015/example.js:39:24 - error NG6001: The class 'ExampleComponent' is listed in the declarations of the NgModule 'ExampleModule', but is not a directive, a component, or a pipe.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 36 (22 by maintainers)

Commits related to this issue

Most upvoted comments

@klemenoslaj Thanks for testing! And indeed, the emitted JS is different for those variants so we need to handle that as well. I can get that sorted out in the PR, shouldn’t be too much trouble.

While working on this yesterday I noticed a bug for numeric enums even for the original TypeScript code, so there’s some more work to be done in this area.

@klemenoslaj ngcc supports a lot of syntax that is specific to a certain emit format. E.g. classes don’t look like classes in ES5, module imports don’t look like modules in UMD etc. but ngcc is still able process them as such. Some of this work is supported by TypeScript through project Salsa, but also a lot of heavy lifting to make it all work is done in ngcc itself.

Support for enums is not done as part of project Salsa and we don’t currently handle it specially in ngcc, so it fails to work. Any other syntax that is emitted into JavaScript in a different way than the original source code may also need special handling to make it appear as the original code, but this is only really needed for when it is part of code that must be statically evaluated at compile time.

Oh, there were actually two bugs and I only fixed one. The remaining one is a bit more complex, it would seem.

TypeScript emits enums in JavaScript as follows:

var Example;
(function (Example) {
    Example["Value"] = "Title";
})(Example || (Example = {}));

Therefore, it’s no longer syntactically an enum, and ngcc needs specialized support to make sense of this structure.

The whole template literal was a distraction, although there was a bug there as well. That part got fixed in cbc25bbf31b84b0d350af7f92c15cfcba183d7c9, the enum support did not. Sorry for not actually verifying the fix with your repro, I should have done that!

Hi @klemenoslaj,

thanks for letting us know, this was indeed part of 9.1.1. I’ll look at it again, sorry for the inconvenience!

@petebacondarwin, @paresh-bhave misunderstood me, sorry for being unclear 😦. The issue is still there, please have a look at my edit.

As I wrote the initial, easy reproduction is fixed, however the template literal within the binding as shown in an issue is still broken.

Please check the repo I have provided in an edit. Can we please re-open this issue? I don’t want to copy paste.

EDIT

@petebacondarwin Thanks for re-opening, and sorry for the confusion caused.

I apologise for the confusion as well

This does appear to be a valid bug when we are trying to convert an ES5 expression to a string before parsing it as a template. E.g.

"abc" + MyEnum.Value + "def"

At the moment this does not get evaluated to a string. (It works in ngtsc because that is working directly with the template string literal (backticked string).

Tracking as FW-1951

Thanks for the info. I will close this issue. Please open a new issue if there are still any unresolved problems.

@paresh-bhave thanks for the investigation. I will double-check later today on my side and will report the results. I will provide the repository if I manage to reproduce it still.