im trying to creater a marker with popup on click, so far so good, the problem is when im trying to set the content of the popup to be my custom tag, for example
let popup = new mapboxgl.Popup()
.setHTML("<custom-tag></custom-tag>")
I know about the option of setDOMContent but I didn't manage to get it right... it suppose to work with document.createElement('custom-tag') so if you can help me on how to use it with custom ponents. thank you for your help!
im trying to creater a marker with popup on click, so far so good, the problem is when im trying to set the content of the popup to be my custom tag, for example
let popup = new mapboxgl.Popup()
.setHTML("<custom-tag></custom-tag>")
I know about the option of setDOMContent but I didn't manage to get it right... it suppose to work with document.createElement('custom-tag') so if you can help me on how to use it with custom ponents. thank you for your help!
Share Improve this question asked Jan 12, 2018 at 15:53 michael ehrlichmichael ehrlich 731 silver badge5 bronze badges 4- where does the ponent '<custom-tag>' e from ? From angular ? If its true, I don't think angular will parse your DOM at runtime, pile and include your ponent – ttncrch Commented Jan 12, 2018 at 15:56
- what do you mean by 'pile and include your ponent'? the 'custom-tag' is a ponet with ts and html i created – michael ehrlich Commented Jan 12, 2018 at 16:00
- Angular doesn't know you dynamically added a tag. So he doesn't know he need to re rende your ponent. – ttncrch Commented Jan 12, 2018 at 16:12
- how do i tell angular to include my ponent? – michael ehrlich Commented Jan 12, 2018 at 16:36
1 Answer
Reset to default 19I was able to get this to work using the Angular ComponentFactoryResolver
. There's a bit of setup, but once you get it working, you can use it to render any ponent you want (and put it anyplace you'd like...including a mapbox popup).
I'm not sure if this is still the "right" way to do this (I'm still on Angular v5) but it does work.
1) Create Dynamic Component Service (can't recall where I got this...sorry for no attribution whoever you are)
import { Injectable, Injector, ApplicationRef, ComponentFactoryResolver, ComponentRef, Type } from '@angular/core'
@Injectable()
export class DynamicComponentService {
private pRef: ComponentRef<any>;
constructor(private injector: Injector,
private resolver: ComponentFactoryResolver,
private appRef: ApplicationRef) { }
public injectComponent<T>(ponent: Type<T>, propertySetter?: (type: T) => void): HTMLDivElement {
// Remove the Component if it Already Exists
if (this.pRef) this.pRef.destroy();
// Resolve the Component and Create
const pFactory = this.resolver.resolveComponentFactory(ponent);
this.pRef = pFactory.create(this.injector);
// Allow a Property Setter to be Passed in (To Set a Model Property, etc)
if (propertySetter)
propertySetter(this.pRef.instance);
// Attach to Application
this.appRef.attachView(this.pRef.hostView);
// Create Wrapper Div and Inject Html
let div = document.createElement('div');
div.appendChild(this.pRef.location.nativeElement);
// Return the Rendered DOM Element
return div;
}
}
2) Use the service to render your custom ponent in the mapbox-gl popup
import { MyCustomMapboxPopup } from "../app/ponents/my-custom-mapbox-popup.ponent"
import { DynamicComponentService } from "../services/dynamic-ponent";
...
// Inside a map.on("click") or wherever you want to create your popup
// Inject Component and Render Down to HTMLDivElement Object
let popupContent = this.dynamicComponentService.injectComponent(
MyCustomMapboxPopup,
x => x.model = new PopupModel()); // This Is where You can pass
// a Model or other Properties to your Component
new mapboxgl.Popup({ closeOnClick: false })
.setLngLat(...wherever you want the popup to show)
.setDOMContent(popupContent)
.addTo(map);
...
Just to avoid any confusion, the custom popup ponent might look something like:
import { Component } from '@angular/core';
@Component({
selector: "custom-mapbox-popup",
templateUrl: "./my-custom-mapbox-popup.ponent.html"
})
export class MyCustomMapboxPopup {
public model: PopupModel; // Model Property
}
// HTML
<div class="my-custom-popup">
<div *ngIf="model">
<h3>{{this.model.SomeModelProperty}}</h3>
</div>
</div>