Select to view content in your preferred language

Custom UI component with Angular

1066
6
Jump to solution
08-16-2023 02:55 PM
ForrestLin
Frequent Contributor

There is sample of Custom UI component with React and Vite:

https://github.com/Esri/jsapi-resources/tree/main/esm-samples/jsapi-custom-ui

 

Is there any sample of Custom UI component with Angular?

0 Kudos
1 Solution

Accepted Solutions
ForrestLin
Frequent Contributor

I have resolved this problem.

import { Injectable, Injector, Renderer2, RendererFactory2} from "@angular/core";
import { createCustomElement, NgElement, WithProperties } from '@angular/elements';
import CustomContent from "@arcgis/core/popup/content/CustomContent";
import { MyPopupComponent } from "../popup/my-popup.component";
 
@Injectable({
  providedIn: 'root'
})
export class RendererService {
 
private _renderer2: Renderer2;
 
constructor(injector: Injector, rendererFactory: RendererFactory2) {
    this._renderer2 = this._rendererFactory.createRenderer(null, null);
 
    const myPopup = customElements.get('my-popup');
    if (!myPopup ) {
      const myPopup = createCustomElement(MyPopupComponent, { injector });
      customElements.define('my-popup', myPopup);
    }
}
 
public createCustomContent(): CustomContent {
    const customContent = new CustomContent({
      outFields: ["*"],
      creator: (event) => {
        const myPopup: NgElement & WithProperties<MyPopupComponent> = this._renderer2.createElement('my-popup');
        myPopup.graphic = event?.graphic;
        return myPopup;
      }
    });
    return customContent;
  }
}

View solution in original post

0 Kudos
6 Replies
AndyGup
Esri Regular Contributor

Hi @ForrestLin  there is not an Angular sample. However, the conceptual doc's Introduction spells out how to do it in any framework: https://developers.arcgis.com/javascript/latest/custom-ui/#introduction.

0 Kudos
ForrestLin
Frequent Contributor

If I have Angular component "my-ui", what's the Custom UI component?  {<app-my-ui><app-my-ui>}?

0 Kudos
ForrestLin
Frequent Contributor

I want to create a CustomContent for popup. I have an Angular component "my-popup". Is it right?

createCustomContent(): CustomContent{
    const contentPromise = new CustomContent({
    outFields: ["*"],
    creator: (event) => {
      return `<app-my-popup></app-my-popup>`;
    }
  });

  return contentPromise;
  }
0 Kudos
AndyGup
Esri Regular Contributor

Yes, you seem to be on the right right track for integrating the CustomContent Class: https://developers.arcgis.com/javascript/latest/api-reference/esri-popup-content-CustomContent.html.  The CustomContent.creator function can be used to return an HTMLElement. In  your case this will be an Angular component. You'll need to pay attention to data binding and component life-cycle. Experiment and see how it goes. Please post your findings here so others can learn, or others may have already gone down this path and respond back.

0 Kudos
ForrestLin
Frequent Contributor

Thank you, Andy!

I found some clue:  dynamic component loading (https://angular.io/guide/dynamic-component-loader#dynamic-component-loading). 

It's using viewContainerRef of directive to create component and set up data:

const viewContainerRef = this.adHost.viewContainerRef;

viewContainerRef.clear();

const componentRef = viewContainerRef.createComponent<AdComponent>(adItem.component);

componentRef.instance.data = adItem.data;

But how to get ViewContainerRef of the popup content in our case?

Capture1.PNG

0 Kudos
ForrestLin
Frequent Contributor

I have resolved this problem.

import { Injectable, Injector, Renderer2, RendererFactory2} from "@angular/core";
import { createCustomElement, NgElement, WithProperties } from '@angular/elements';
import CustomContent from "@arcgis/core/popup/content/CustomContent";
import { MyPopupComponent } from "../popup/my-popup.component";
 
@Injectable({
  providedIn: 'root'
})
export class RendererService {
 
private _renderer2: Renderer2;
 
constructor(injector: Injector, rendererFactory: RendererFactory2) {
    this._renderer2 = this._rendererFactory.createRenderer(null, null);
 
    const myPopup = customElements.get('my-popup');
    if (!myPopup ) {
      const myPopup = createCustomElement(MyPopupComponent, { injector });
      customElements.define('my-popup', myPopup);
    }
}
 
public createCustomContent(): CustomContent {
    const customContent = new CustomContent({
      outFields: ["*"],
      creator: (event) => {
        const myPopup: NgElement & WithProperties<MyPopupComponent> = this._renderer2.createElement('my-popup');
        myPopup.graphic = event?.graphic;
        return myPopup;
      }
    });
    return customContent;
  }
}
0 Kudos