Get Selected Features in Custom Widget

744
12
Jump to solution
04-21-2021 06:00 AM
AdrianAkbariNet4s
New Contributor II

Hi, 

How can I create a custom widget in experience builder that takes the current selected features from the standard selection tool?

I have read the docs and looked at the sample repos but I still cant manage to do it. Any help is appreciated jimu documentation is not really helping. 

 

Thanks. 

0 Kudos
1 Solution

Accepted Solutions
AdrianAkbariNet4s
New Contributor II

Hi Sam, 

I can explain you a little bit about that. I suggest you start by cloning one of the existing sapmple widgets. That makes your life much easier since the JIMU documentation is not very complete. For this case you can use for example: 

https://github.com/Esri/arcgis-experience-builder-sdk-resources/tree/master/samples/widgets/feature-...

or

https://github.com/Esri/arcgis-experience-builder-sdk-resources/tree/master/samples/widgets/feature-....

In the sample above the part the dataRender function is where you should be working to get selected features. There, if you change the: 

...ds.getRecords().map((ri)...
to
...ds.getSelectedRecords().map((ri)...
 
you will have the selected records. (So I basically changed getRecords with getSelectedRecords). 
 
This should help you to get further. 
 
I share my complete function here in case it helps.
 
 

 

dataRender = (ds: DataSource, info: IMDataSourceInfo) => {
    // this.createOutputDs(ds);
    const fName = this.props.useDataSources[0].fields[0];
    let selectedAttributes = [];
    for (let i = 0; i < ds.getSelectedRecords().length; i++){
      selectedAttributes.push(ds.getSelectedRecords()[i].getData()[fName]);
      selectedAttributes.push(<br/>)
    };
    // ds.getSelectedRecords().forEach(element => {
    //   selectedAttributes.push(element.getData()[fName]);
    // });
    this.setState({
      selectedRecords: selectedAttributes
    });
    
    return <>
      
      <div> 
        <p> Selected Records:</p>
      </div>
      <div className="record-list" style={{ width: '100%', marginTop: '20px', marginBottom: '20px', height: 'auto', overflow: 'auto' }}>
        {
          ds && ds.getStatus() === DataSourceStatus.Loaded ? ds.getSelectedRecords().map((r, i) => {
            return <div key={i}>{r.getData()[fName]}</div>
          }) : null
        
        }
      </div>
      
    </>
  }

 

View solution in original post

12 Replies
DavidMartinez
Esri Regular Contributor

Can you describe your workflow? What is the behavior after you get the selected features? Do you use those in another widget? I think a better approach would be to use the query widget with the draw tool to get the features inside the drawn shape which generates an output data source. Then you could use that output data source in other widgets. The 1.4 release of the dev edition will have the query widget as well as samples on how to use an output data source if you need to use that in another custom widget. 

 

Cheers,

 

David 

AdrianAkbariNet4s
New Contributor II

Hi David, 

I want to get a selected feature then make a http(s) request (fetch) and send it's attributes to run a python tool online. So no I am not gonna use it in another widget.  

Maybe Query widget helps with this workflow partially but in the end I still need my custom widget to send the http call. 

Any idea when 1.4 dev edition will be released? 

0 Kudos
DavidMartinez
Esri Regular Contributor

If it is an individual feature you will need to have a click event on the map, get the graphics layer and then do a query and pass the attributes to the python tool.  If you want it to work off the map selection tool you're going to need to modify the computerSelectedGraphics method located in the selected-number.tsx file in the map widget. 

Cheers,


David

0 Kudos
Sam_Berg
New Contributor III

@DavidMartinez can you suggest how a custom widget can access an existing selected feature in a layer?  Mostly I am trying to resolve an issue in that the editor widget sample does not seem to pick up the selected feature in the map when it loads requiring an extra map click.  https://community.esri.com/t5/arcgis-experience-builder/editor-widget-and-picking-up-the-current-sel... I was investigating a workaround to use something like startUpdateWorkflowAtFeatureSelection(f) to try and trigger the expected behavior.  But if you have feedback on the general issue and approach to the problem I would be grateful, thanks.

0 Kudos
AdrianAkbariNet4s
New Contributor II

Hi Sam, 

I can explain you a little bit about that. I suggest you start by cloning one of the existing sapmple widgets. That makes your life much easier since the JIMU documentation is not very complete. For this case you can use for example: 

https://github.com/Esri/arcgis-experience-builder-sdk-resources/tree/master/samples/widgets/feature-...

or

https://github.com/Esri/arcgis-experience-builder-sdk-resources/tree/master/samples/widgets/feature-....

In the sample above the part the dataRender function is where you should be working to get selected features. There, if you change the: 

...ds.getRecords().map((ri)...
to
...ds.getSelectedRecords().map((ri)...
 
you will have the selected records. (So I basically changed getRecords with getSelectedRecords). 
 
This should help you to get further. 
 
I share my complete function here in case it helps.
 
 

 

dataRender = (ds: DataSource, info: IMDataSourceInfo) => {
    // this.createOutputDs(ds);
    const fName = this.props.useDataSources[0].fields[0];
    let selectedAttributes = [];
    for (let i = 0; i < ds.getSelectedRecords().length; i++){
      selectedAttributes.push(ds.getSelectedRecords()[i].getData()[fName]);
      selectedAttributes.push(<br/>)
    };
    // ds.getSelectedRecords().forEach(element => {
    //   selectedAttributes.push(element.getData()[fName]);
    // });
    this.setState({
      selectedRecords: selectedAttributes
    });
    
    return <>
      
      <div> 
        <p> Selected Records:</p>
      </div>
      <div className="record-list" style={{ width: '100%', marginTop: '20px', marginBottom: '20px', height: 'auto', overflow: 'auto' }}>
        {
          ds && ds.getStatus() === DataSourceStatus.Loaded ? ds.getSelectedRecords().map((r, i) => {
            return <div key={i}>{r.getData()[fName]}</div>
          }) : null
        
        }
      </div>
      
    </>
  }

 

View solution in original post

Sam_Berg
New Contributor III

Thank you @AdrianAkbariNet4s.  Are you able to describe how to incorporate the ds.getSelectedRecords() into the Editor Widget sample workflow where an ActiveMapView is used to access the layer necessary to initialize an editor widget?  Thanks for any info, and I appreciate the response here!

0 Kudos
Sam_Berg
New Contributor III

What I have working just now is a custom editor widget with both a JimuMapViewComponent and DataSourceComponent.  The editor widget is configured with the configured layer read in ActiveViewChanged, and that layer saved in state.  Then on DataRender I am getting the selection as suggested by @AdrianAkbariNet4s and used to create a feature with the layer reference to pass to startUpdateWorkflowAtEdit.

 

 

      if(this.state && this.state.currentWidget  && ds.getSelectedRecords().length==1){
        let g=new Graphic();
        g.attributes=ds.getSelectedRecords()[0].getData();
        g.layer=this.state.currentEditLayer;
        this.state.currentWidget.startUpdateWorkflowAtFeatureEdit(g);
      }

 

 

 This seems to have the behavior I am looking for which keeping the editor in sync with feature selection changes.  Thank you.  Sam

AlejandroMari1
New Contributor III

Hi all! How do you keep up with the selection changed on the data source from another widget? I can't figure that out. Basically I want a callback or something on my widget when the selection has changed from another widget... I couldn't find anything on the <DataSourceComponent>  or the DataSource object itself that will provide that.

0 Kudos
AdrianAkbariNet4s
New Contributor II

I am not sure what you exactly want to do when the selection changes. Do you mean for example when a selection is changed via selection widget on the map, then your custom widget automatically takes the updated selection? 

In that case you can try stroring your selected features/graphics as a state. Then React will automatically takes care of the updates. This way you can also do something if state changes. 

0 Kudos