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 components. thank you for your help!
I 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 component 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 compRef: ComponentRef<any>;
constructor(private injector: Injector,
private resolver: ComponentFactoryResolver,
private appRef: ApplicationRef) { }
public injectComponent<T>(component: Type<T>, propertySetter?: (type: T) => void): HTMLDivElement {
// Remove the Component if it Already Exists
if (this.compRef) this.compRef.destroy();
// Resolve the Component and Create
const compFactory = this.resolver.resolveComponentFactory(component);
this.compRef = compFactory.create(this.injector);
// Allow a Property Setter to be Passed in (To Set a Model Property, etc)
if (propertySetter)
propertySetter(this.compRef.instance);
// Attach to Application
this.appRef.attachView(this.compRef.hostView);
// Create Wrapper Div and Inject Html
let div = document.createElement('div');
div.appendChild(this.compRef.location.nativeElement);
// Return the Rendered DOM Element
return div;
}
}
2) Use the service to render your custom component in the mapbox-gl popup
import { MyCustomMapboxPopup } from "../app/components/my-custom-mapbox-popup.component"
import { DynamicComponentService } from "../services/dynamic-component";
...
// 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 component might look something like:
import { Component } from '@angular/core';
@Component({
selector: "custom-mapbox-popup",
templateUrl: "./my-custom-mapbox-popup.component.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>
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