can't figure out how to generate a component into a leaflet popup. I've tried two things:
First, integrate the component selector into the html but it looks as if angular does not compile it:
let my geojson = L.geoJSON(data, {
onEachFeature: (feature, layer) => {
let popup = L.popup().setContent('<app-component-detail></app-component-detail>');
layer.on({
click: () => {
layer.bindPopup(popup);
}
})
}
}).addTo(map);
When i click on a point on the map, the popup is empty.
Then i considered using "resolveComponentFactory" to generate the component into a ViewContainerRef. It works well if i call an element of my view with @ViewChild:
Template:
<div #myContainer></div>
logic:
@ViewChild('myContainer', { read: ViewContainerRef } ) myContainer: ViewContainerRef;
private generatedComponent= this.componentFactoryResolver.resolveComponentFactory(componentDetail);
let my geojson = L.geoJSON(data, {
onEachFeature: (feature, layer) => {
layer.on({
click: () => {
this.myContainer.createComponent(this.generatedComponent);
}
})
}
}).addTo(map);
Now i would like to generate my component directly into a popup. I think i need to set a ViewContainerRef into the content of my popup. Something like that:
@ViewChild('popup', { read: ViewContainerRef } ) popup: ViewContainerRef;
private generatedComponent= this.componentFactoryResolver.resolveComponentFactory(componentDetail);
let my geojson = L.geoJSON(data, {
onEachFeature: (feature, layer) => {
let popup = L.popup().setContent('<div #popup></div>');
layer.on({
click: () => {
layer.bindPopup(popup);
this.popup.createComponent(this.generatedComponent);
}
})
}
}).addTo(map);
EDIT: Here is how i transposed this solution to leaflet.js
let geojson = L.geoJSON(data, {
style: () => defaultStyle,
onEachFeature: (feature, layer) => {
let popup = L.popup();
layer.on({
click: () => {
this.zone.run( () => {
if(this.componentRef){
this.componentRef.destroy();
}
const compFactory = this.componentFactoryResolver.resolveComponentFactory(componentDetailmponent);
this.componentRef = compFactory.create(this.injector);
if (this.appRef['attachView']) { // since 2.3.0
this.appRef['attachView'](this.componentRef.hostView);
this.componentRef .onDestroy(() => {
this.appRef['detachView'](this.componentRef.hostView);
});
} else {
this.appRef['registerChangeDetector'](this.componentRef.changeDetectorRef);
this.componentRef.onDestroy(() => {
this.appRef['unregisterChangeDetector'](this.componentRef.changeDetectorRef);
});
}
let div = document.createElement('div');
div.appendChild(this.componentRef.location.nativeElement);
popup.setContent(div);
}
)
}
});
layer.bindPopup(popup);
}
});
this is a working solution:
Create Component
component = this.resolver.resolveComponentFactory(PopupComponent).create(this.injector);
Use NG component as HTML:
component.location.nativeElement
ex:
this.bindPopup(this.component.location.nativeElement);
Where:
Remember to add 'app.module.ts':
entryComponents: [PopupComponent]
EXTRA
Angular must be notified about "change", call:
component.changeDetectorRef.detectChanges()
If you want to use input fields in the popup:
DomEvent.disableClickPropagation(this.component.location.nativeElement);
:)
@miguel-de-matos
const component = this.resolver.resolveComponentFactory(MyComponent).create(this.injector);
component.instance.title = 'Super Title';
component.changeDetectorRef.detectChanges();
Here is how i transposed this solution to leaflet.js:
let geojson = L.geoJSON(data, {
onEachFeature: (feature, layer) => {
let popup = L.popup();
layer.on({
click: () => {
this.zone.run( () => {
if(this.componentRef){
this.componentRef.destroy();
}
const compFactory = this.componentFactoryResolver.resolveComponentFactory(componentDetailmponent);
this.componentRef = compFactory.create(this.injector);
if (this.appRef['attachView']) { // since 2.3.0
this.appRef['attachView'](this.componentRef.hostView);
this.componentRef .onDestroy(() => {
this.appRef['detachView'](this.componentRef.hostView);
});
} else {
this.appRef['registerChangeDetector'](this.componentRef.changeDetectorRef);
this.componentRef.onDestroy(() => {
this.appRef['unregisterChangeDetector'](this.componentRef.changeDetectorRef);
});
}
let div = document.createElement('div');
div.appendChild(this.componentRef.location.nativeElement);
popup.setContent(div);
}
)
}
});
layer.bindPopup(popup);
}
});
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