Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Could not resolve type Document in angular5

I want to add a CSS class dynamically on the click of a button on the body tag. So I am using the DOCUMENT object of angular. Here is the code

import { DOCUMENT } from "@angular/platform-browser";

... component code

constructor( @Inject(DOCUMENT) private document: Document) { }

addClass() {
    this.document.body.classList.add("any_class");
}

but this is showing errors

Metadata collected contains an error that will be reported at runtime: Could not resolve type Document.
[0]   {"__symbolic":"error","message":"Could not resolve type","line":50,"character":53,"context":{"typeName":"Document"}}
[0]     at \node_modules\@angular\compiler-cli\src\metadata\collector.js:664:27
[0]     at Array.forEach (<anonymous>)
[0]     at validateMetadata (D:\QPP Workspace\QWC\QWC\node_modules\@angular\compiler-cli\src\metadata\collector.js:652:42)
[0]     at MetadataCollector.getMetadata (D:\QPP Workspace\QWC\QWC\node_modules\@angular\compiler-cli\src\metadata\collector.js:507:17)
[0]     at LowerMetadataCache.getMetadataAndRequests (ProjectPath\node_modules\@angular\compiler-cli\src\transformers\lower_expressions.js:264:39)
[0]     at LowerMetadataCache.ensureMetadataAndRequests (ProjectPath\node_modules\@angular\compiler-cli\src\transformers\lower_expressions.js:209:27)
[0]     at LowerMetadataCache.getRequests (ProjectPath\node_modules\@angular\compiler-cli\src\transformers\lower_expressions.js:204:21)
[0]     at ProjectPath\node_modules\@angular\compiler-cli\src\transformers\lower_expressions.js:146:36
[0]     at ProjectPath\node_modules\typescript\lib\typescript.js:2601:86
[0]     at reduceLeft (ProjectPath\node_modules\typescript\lib\typescript.js:2274:30)
error Command failed with exit code 2.
[0]     at ChildProcess.exithandler (child_process.js:275:12)
[0]     at emitTwo (events.js:126:13)
[0]     at ChildProcess.emit (events.js:214:7)
[0]     at maybeClose (internal/child_process.js:925:16)
[0]     at Process.ChildProcess._handle.onexit (internal/child_process.js:209:5)

What is the issue? I am using angular5. And is there any other way to add class dynamically?

like image 564
Sunil Garg Avatar asked Mar 27 '18 12:03

Sunil Garg


2 Answers

You'll get this error if using something like

@Inject(DOCUMENT) document: Document

with your compiler settings in your tsconfig.json set to

"angularCompilerOptions": {
  "strictMetadataEmit": true
}

It turns out that the angular compiler doesn't understand the type Document when working out the metadata for injectable parameters, even though it understands the injection token DOCUMENT, and Typescript understands type Document.

This is documented here: https://github.com/angular/angular/issues/20351

The workaround that I use is:

@Injectable({
  providedIn: 'root'
})
class MyService {

  constructor(@Inject(DOCUMENT) document?: any) {
    this._document = document as Document;
  }

  private _document?: Document;

...

This uses any for the injection signature (making angular happy), but gives you Typescript types within the class.


Note: This is no longer an issue with Ivy on Angular 9 or later. You can just use:

constructor(
  @Inject(DOCUMENT) readonly document: Document
) {}
like image 130
crimbo Avatar answered Sep 17 '22 07:09

crimbo


You can add "/** @dynamic */" before your component's decorator:

/** @dynamic */
@Component({

to suppress the error as mentioned here https://github.com/angular/angular/issues/20351#issuecomment-344009887 and here https://angular.io/guide/aot-compiler#strictmetadataemit

like image 27
Guillaume Blanchet Avatar answered Sep 21 '22 07:09

Guillaume Blanchet