-
Notifications
You must be signed in to change notification settings - Fork 126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom Components in marker popups. #178
Comments
You can do this by using Angular 6 NgElement
|
Expanding on @zellb 's comment, here is how I achieved custom angular components in leaflet popups.. popup.component.ts:
In your app.modules.ts declare your pop up component, set it as an
Then given my leaflet-map.component.ts:
and my leaflet.service.ts:
You can see that I can add the component dynamically using @reblace if you would like I could add a more generic example to the docs and open a PR for it. |
Where is that esri-leaflet from? |
It's this library: https://esri.github.io/esri-leaflet/ Should probably take that out for a more generic example. |
Thank you. It is possible to solve the problem without that library? I saw that you have called esri.featureLayer function |
@zachatrocity Are you going to provide a more generic example here? |
sure, you don't have to use esri.FeatureLayer, you could just use anything that accepts a
|
I have an example of having markers themselves as Angular components. |
Thanks to your @zachatrocity and @mcurtis22 help I was abble to do waht I needed. This tutorial (https://www.techiediaries.com/angular-elements-web-components/) was also very useful to learn how to create custom elements. I was missing the @angular/elements install. cheers! |
@zachatrocity @mcurtis22 Have you tried to use reactive forms on your custom element ? |
@lourencoGit like inside the custom popup component? No i haven't. What issues are you having? |
@zachatrocity the component dom was not being updated after some action, like error messages, ng-if condition changes, I solved it calling this.changeDetectorRef.detectChanges(); |
can someone provide a solution for Angular 4/5? |
@JamesHearts the repo I linked should be Angular 4 compatible, the original code was taken from an Angular 2 project. @lourencoGit sorry for the delay, I did not use reactive forms, and had to also manually invoke change detection. |
When I follow these examples I get the following console error?
Edit: apparently it is necessary to |
+1 |
@JamesHearts see my comment above: |
@reblace pretty sure this issue could be closed with some documentation. |
It's not clear what fires the 'closed' event. |
on angular 12 I need to install @angular/elements with ng add @angular/elements |
@zachatrocity I tried your solution, and it worked for me. I am able to show my custom component inside the popup. Any suggestion ? |
Hi everyone. Whatever I tried, it did not work. For example, the popup got removed after clicking twice on it. However, the idea @mcurtis22 proposed does work. So I want to generalize it a bit: SolutionAt first, you do not need @angular/elements. The ComponentFactoryResolver works great and for me more reliable than elements. Creating the Component:Create a template for a popup. This component needs to be added in the declarations array of your module. popup.component.ts
PopupServiceUse a service methode to get the HTMLElement popup.service.ts
Call the methode and bindPopupNow you can generate a popup with given data. app.component.ts
|
Thank you for sharing your solution @Morstis ! |
This solution has the problem that componentFactoryResolver is deprecated up from Angular 13 (see: Documentation). In the documentation they propose to use ViewContainerRef.createComponent(). The problem with this is that this function does not support the rootSelectorOrNode property that @Morstis used in the factory.create function. I did not manage to bind the created CompoentRef to the HTML element, therefore this approach did not work for me in Angular 14. The approach using angular elements mentioned earlier worked nevertheless. |
@lowickert or whoever is interested: The solution by @Morstis works (again?) by now with some modifications. We can use the function import {ApplicationRef,createComponent, EnvironmentInjector, Injectable, Injector} from '@angular/core';
import {PopupComponent} from '../components/popup.component';
@Injectable({ providedIn: 'root' })
export class PopupService {
constructor(
private injector: Injector,
private environmentInjector: EnvironmentInjector,
private applicationRef: ApplicationRef
) { }
returnPopUpHTML(popupData: MapPopup): HTMLElement {
const element = document.createElement("div")
const component = createComponent(PopupComponent, {
elementInjector: this.injector,
environmentInjector: this.environmentInjector,
hostElement: element
});
this.applicationRef.attachView(component.hostView);
component.instance.popup = popupData;
return element;
}
} |
@neuged, I tried this approach (Angular 14.3.0) and it seems to work, but it also seems to create a memory leak when removing and redrawing markers. In the Chrome heap snapshots you can see the amount of Detached HTMLDivElements rising when markers are removed and redrawn. Anyone else run into this? It's creating some performance problems when removing and redrawing a sizeable number of markers. |
@jakebeinart Yes, if you redraw the markers, it is probably necessary to manually destroy the refs you created once you do not need them anymore, you might also want to remove the HTML elements. We actually ended up collecting all the components/elements in two arrays in the service and removing them in a class PopupService {
private elements: HTMLElement[] = [];
private refs: ComponentRef<unknown>[] = [];
returnPopUpHTML(popupData: MapPopup): HTMLElement {
...
this.refs.push(component);
this.elements.push(element);
return element;
}
cleanup(): void {
this.refs.splice(0).forEach((ref) => ref.destroy());
this.elements.splice(0).forEach((element) => element.remove());
}
} (For a full example with Marker and Popup components, you can see this gist btw) |
We are using a version of the solution @Morstis and @neuged suggested with one major difference: Instead of we do something like this
Unfortunately, this breaks the change detection. Initial hover over the marker shows only a small white box and only clicking somewhere else renders the popup correctly. After this initial hickup, the popup works as intended (with button clicks etc). Adding Does anyone know of this problem and can provide a possible solution? |
It would be great if there is a possibility to customize the marker popups with custom angular components.
The text was updated successfully, but these errors were encountered: