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