Select to view content in your preferred language

How can I get layerId in Experience Builder (Developer Edition)

1623
2
01-17-2023 06:58 AM
Nadiia_Matsiuk
Occasional Contributor

Hi!

I try to create hover pop up in custom widget (related post: https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/hover-popup-experience-builder-de...). In my opinion, one possible way of implementation is layerId tracking. For example, hitTest() look for layerId on map, if there is graphic element popup is open. When mouse move out from layer popup is close. If there isn't any layer pop up isn't call.

I use these components in code but I can't do anything in right way. It doesn't work. I can't found layerId option and add it to equally method.

Thanks a lot for any advice! 

 

 

 

 

/** @jsx jsx */
import { React, AllWidgetProps, jsx, IMDataSourceInfo, DataSource, DataSourceManager, DataSourceStatus, FeatureLayerQueryParams, DataSourceComponent } from 'jimu-core'
import { JimuMapViewComponent, JimuMapView, FeatureLayerDataSource } from "jimu-arcgis";
import { result } from 'lodash-es';
import View from 'esri/views/View';
import {DataSourceSelector, AllDataSourceTypes, FieldSelector} from 'jimu-ui/advanced/data-source-selector';
import { viewChangeBufferCompare } from 'dist/widgets/arcgis/bookmark/src/setting/utils';

export const myFeatureLayer={} as const

export default class Widget extends React.PureComponent<AllWidgetProps<any>, any>{

    state = {
      jimuMapView: null,
      timer: null,
      allLayer: [],
      lyr: null
    };

    getDataSourceByLayer: (layerId: string | number, layerOfSubLayerId?: string) => DataSource

    onDataSourceCreated = (ds: DataSource) => {
      const datasrc=this.props.useDataSources[0]
      const myDatasrc=DataSourceManager.getInstance().getDataSource(dataSrc.dataSourceId) as FeatureLayerDataSource
      const myFeatureLayer = myDataSrc.layer
      this.setState({ allLayer: myFeatureLayer.layerId, lyr: myFeatureLayer })
    }

    doHitTest = (evt: PointerEvent) => {
      if(this.state.jimuMapView){
        // Run hitTest on the map view using the pointer event
        this.state.jimuMapView.view.hitTest(evt).then((response) => {
          if(response.results.length){
            const graphic = response.results.filter(function (result) {
              return result.graphic.layer === myFeatureLayer;
            })[0].graphic
            this.state.jimuMapView.view.popup.open({
              location: graphic.geometry.centroid, 
              features: [graphic]
            });
          } else {
            this.state.jimuMapView.view.popup.close();
          }
        })
      }
    }

    activeViewChangeHandler = (jmv: JimuMapView) => {
      if (jmv) {
        this.setState({
          jimuMapView: jmv
        });
        // register the pointer-move event handler on the map view
        jmv.view.on("pointer-move", (evt) => {
          // if there is already a timer, cancel it
          if(this.state.timer){
            clearTimeout(this.state.timer)
          }
          // set new timer that will call doHitTest after the interval
          // pass the pointer-move event as the parameter to doHitTest
          this.setState({
            timer: setTimeout(this.doHitTest, 0, evt)
          })
        });
      }
    };

    render() {
      return (
        <div className="widget-hoverPopup jimu-widget">
          {this.props.hasOwnProperty("useMapWidgetIds") &&
            this.props.useMapWidgetIds &&
            this.props.useMapWidgetIds[0] && (
              <JimuMapViewComponent
                useMapWidgetId={this.props.useMapWidgetIds?.[0]}
                onActiveViewChange={this.activeViewChangeHandler}
              />
            )
          }
        </div>
      );
    }

}

 

 

 

 

0 Kudos
2 Replies
UndralBatsukh
Esri Regular Contributor

Hi there, 

So I tried my best to understand what problem you are trying to solve. I apologize if I did not understand the issue you are trying to solve. Seems like you want to display popupTemplate for only selected layers when user moves the mouse over the map? At least I think this is what you are asking. 

Displaying popupTemplate from pointer-move is intense. So I suggest you use debounce method to improve the app performance. 

The MapView.hittest method lets you specify which layers you want to include in the hittest result. So you can specify the layers there. This way the hittest will return results only for those layers. You can also set the exclude to specify layers to be excluded from the hittest. Hope this helps! 

The following codepen app displays popupTemplate from pointer-move event. It uses include parameter to specify to only include cities feature layer to be included in the hittest. It also uses debounce for the hittest so you can "debounce", or cancel the function execution, until the previous execution of the same function call finishes.

https://codepen.io/U_B_U/pen/KKBZmzq?editors=1000

 

 

 

Nadiia_Matsiuk
Occasional Contributor

@UndralBatsukh Hi!

Thank you very much for this advice! I have been sitting on this task for several weeks...

Actually, I want to create universal popup widget for any map that we add to the Map widget in Experience Builder (Dev edition; see attachment). My problem is that I can't (don't know) how to declare, specify the layer / featureLayer.

In your example featureLayer declare in simple way. It's cool! But when I do that I get the error.

Does the Experience Builder allow to create a pop-up window for some specific graphic layer? How can this be done?

Thank you very much!


Just in case, I am attaching the widget code.

0 Kudos