Could not resolve type Document in angular5

Issue

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?

Solution

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
) {}

Answered By – crimbo

Answer Checked By – Jay B. (AngularFixing Admin)

Leave a Reply

Your email address will not be published.