I'm struggling to make Material Design Lite component to work with dynamically added elements via *ngFor. I understand that I need to call componentHandler.upgradeElement, but where do I put this call? I was trying this and this directives but they don't seem to work. Specifically, I need mdl-menu on each item of my array. Any suggestions on where to look at?
TLDR; You need to call componentHandler.upgradeElement after the elements have been injected into the DOM. An approach I've used in the past is described in the example below.
EDIT If you want a declarative solution this approach here seem like a pretty good one, but I have not used it myself.
I created a service that wraps the Material Lite componentHandler
import { Injectable } from '@angular/core';
export interface ComponentHandler {
upgradeDom();
}
declare var componentHandler: ComponentHandler;
@Injectable()
export class MaterialService {
handler: ComponentHandler;
constructor() {
this.handler = componentHandler;
}
// render on next tick
render() {
setTimeout(() => { this.handler.upgradeDom(); }, 0);
}
}
Then you call the service's render function after the component has injected the elements into the DOM. In your case this is after the *ngFor
This is a very contrived example but demonstrates "where" to call render
import { Component, OnInit } from '@angular/core';
import { DataService } from 'services/data.service';
import { MaterialService } from 'services/material.service';
@Component({
selector: 'app-thing',
templateUrl: `
<ul>
<li *ngFor="let item of data">
{{data}}
</li>
</ul>
`
})
export class ThingComponent implements OnInit {
data: string[]
constructor(
private service: DataService,
private material: MaterialService
) { }
ngOnInit() {
this.service.getData()
.subscribe(data => {
this.data = data;
this.material.render();
});
}
}
Problem: MDL does not watch dynamically created DOM element.
Solution: MDL library adds componentHandler property onto Window object. execute the below code inside ngOnInit() method of the component in which you are adding element dynamically.
setTimeout(() => {
window['componentHandler'].upgradeDom();
}, 0);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With