Hiding widget based on data action

1281
4
Jump to solution
04-27-2022 02:17 AM
SerjStol
New Contributor III

Hello,

I am new to ExB and React. I am trying to create a warning widget that appears only when a specific data is in the extent of the Map widget/view. 

I have figured that I can use Action Trigger in the Map widget to be set on Extent Change and this should apply a Filter on the data source that is accessible to all widgets.

But can I hide a widget from view when no features of the configured data source is in the extent? I see WidgetState only applies to a widget in the Widget Controller. But I don't want it to be in the controller, I just want a message popup and dissapear if no data is visible. 

I have so far reverse engineered Text Widget to make my message but I cannot figure out how to hide/unhide it based on the data action.

Sorry if it sounds totally wrong, maybe I am not understanding it properly.

Regards,

Serj

0 Kudos
1 Solution

Accepted Solutions
SerjStol
New Contributor III

To follow up on this idea. I ended up adding JimuMapViewComponent and using watchUtils  from 'esri/core/watchUtils' to monitor change in map extent via activeViewChangeHandler function and set mapExtent in useState react hook. I then created a useEffect() react hook that executes whenever the mapExtent useState hook state changes, with an async function inside to query the total count of features in the connected data source. 

  React.useEffect(() => {
    if (useDataSources) {
      console.log("Data in extent?: ", dataInExtent)
      console.log("Current Features Count:", featureCount)

      async function getQueryCountResult() {
        let totalFeatures = 0
        for (const connectedDataSource of useDataSources) {

          const dataSourceId = connectedDataSource.dataSourceId
          const dataSource = dataSourceId && DataSourceManager.getInstance().getDataSource(dataSourceId) as QueriableDataSource

          console.log("Layer name: ", dataSource.layerDefinition.name)

          const result = await dataSource.queryCount(getQuery());
          //console.log(result)
          totalFeatures = totalFeatures + result.count
          console.log("Inside query async count:", result.count)
        }
        console.log("Total Features count: ", totalFeatures)
        setFeatureCount(totalFeatures)

        if (totalFeatures > 0) {
          setDataInExtent(true)
        } else {
          setDataInExtent(false)
        }
      }
      getQueryCountResult()
      console.log("Outside count:", featureCount)

    }
  }, [mapExtent])
 
The dataInExtent state changes to true or false based on if the query count is greater than 0 or not. This will then dictate the widget to render or not.
 
For this to work Map Widget Action Triggers need to be configured to filter the data on Extent Change applied on the Framework. So in my custom Text/Message Widget I connect to the same data sources and thats why queryCount will return only the total count of features in the map extent.

View solution in original post

0 Kudos
4 Replies
SerjStol
New Contributor III

Okay I think I figured out how to hide the widget component if variable dataInExtent is false and we are not in the builder environment, basically just return null so nothing gets rendered:

if (dataInExtent || isInBuilder) {
    return (
      <div
        data-testid='text-widget'
        css={style}
        className={classNames('widget-text jimu-widget p-1')}
      >
        {createEditor && <RichEditor
          className={classNames({ 'd-none': !editable })}
          widgetId={id}
          nowrap={!wrap}
          onInitResizeHandler={onInitResizeHandler}
          useDataSources={useDataSources}
          enabled={!!isInlineEditing}
          onCreate={onEditorCreate}
          onDestory={onEditorDestory}
          onChange={onEditorChange}
          placeholder={placeholder}
          preserveWhitespace
          value={text}
        />}
        <Displayer
          className={classNames({ 'd-none': editable })}
          value={text}
          wrap={wrap}
          placeholder={placeholder}
          useDataSources={useDataSources}
          widgetId={id}
          repeatedDataSource={repeatedDataSource as RepeatedDataSource}
        />
      </div>
    )
  } else {
    return null
  }
}
 
 
However, this does not effect the Style settings of the widget. For example, if I want the background colour, this does not get hidden. I guess this is applied somewhere else and I'll need to implement my own background if I want, or just use an image.
 
dataInExtent = true OR inBuilder = true:
SerjStol_0-1651076304376.png

 

dataInExtent = false

 

SerjStol_1-1651076343231.png

 

 
0 Kudos
SerjStol
New Contributor III

Now need to figure out how to get the TotalCount  of features in the Data Source? I think there is a property somewhere I saw in the API. Since Map widget applies a map extent trigger and filters the data, this should come across?

0 Kudos
SerjStol
New Contributor III

To follow up on this idea. I ended up adding JimuMapViewComponent and using watchUtils  from 'esri/core/watchUtils' to monitor change in map extent via activeViewChangeHandler function and set mapExtent in useState react hook. I then created a useEffect() react hook that executes whenever the mapExtent useState hook state changes, with an async function inside to query the total count of features in the connected data source. 

  React.useEffect(() => {
    if (useDataSources) {
      console.log("Data in extent?: ", dataInExtent)
      console.log("Current Features Count:", featureCount)

      async function getQueryCountResult() {
        let totalFeatures = 0
        for (const connectedDataSource of useDataSources) {

          const dataSourceId = connectedDataSource.dataSourceId
          const dataSource = dataSourceId && DataSourceManager.getInstance().getDataSource(dataSourceId) as QueriableDataSource

          console.log("Layer name: ", dataSource.layerDefinition.name)

          const result = await dataSource.queryCount(getQuery());
          //console.log(result)
          totalFeatures = totalFeatures + result.count
          console.log("Inside query async count:", result.count)
        }
        console.log("Total Features count: ", totalFeatures)
        setFeatureCount(totalFeatures)

        if (totalFeatures > 0) {
          setDataInExtent(true)
        } else {
          setDataInExtent(false)
        }
      }
      getQueryCountResult()
      console.log("Outside count:", featureCount)

    }
  }, [mapExtent])
 
The dataInExtent state changes to true or false based on if the query count is greater than 0 or not. This will then dictate the widget to render or not.
 
For this to work Map Widget Action Triggers need to be configured to filter the data on Extent Change applied on the Framework. So in my custom Text/Message Widget I connect to the same data sources and thats why queryCount will return only the total count of features in the map extent.
0 Kudos
UbaidGul_opaz
New Contributor II

Dears,

I have different zones of areas and I have one custom widget which is made particularly for one specific zone I want my user to open my widget using a button but I want that button to be shown only when map extent is on that particular zone. Please suggest some solution.

0 Kudos