Updating Label When Graphic Attributes Update

1023
3
Jump to solution
12-26-2020 02:10 PM
rogenjh
New Contributor III

Hey everyone,

I'm new to ESRI, so I apologize if this is a novice question, but I've been banging my head on it all day and could use a hand. Here's my situation: I'm currently trying to update the color of a label based on an attribute that updates on user events.

1. When User opens a popup, the features attribute is updated to 1.

 

watchUtils.whenDefined(this.view.popup, 'selectedFeature', async (selectedFeature: __esri.Graphic) => {
        if (selectedFeature) {
          selectedFeature.setAttribute('selected', 1);
          const update = await this.currentLayer.applyEdits({updateFeatures: [selectedFeature]});
        }}
      );

 

2.  The UniqueValueRenderer renders different graphics depending on the selected attribute. So far, this all works, and I'm just posting it for context. When the attribute changes, a new graphic appears. 

 

export const UniqueValueRenderer = {
  type: 'unique-value',  // autocasts as new UniqueValueRenderer()
  field: 'type',
  field2: 'selected',
  fieldDelimiter: ', ',
  defaultSymbol: { type: 'simple-fill' },  // autocasts as new SimpleFillSymbol()
  uniqueValueInfos: [{
    value: 'background, 0',
    symbol: backgroundColorSymbol(false)
  }, {
    value: 'background, 1',
    symbol:  backgroundColorSymbol(true)
  }]
};

 

 3. My two label classes include 'where' clauses that differentiate which label is to be applied based on the attribute.

 

export const deSelectedLabelClass = {  
  symbol: {
    type: 'text',
    yoffset: 1.5,
    size: 25, 
    color: '#00789E',
    font: {  
       family: 'Ubuntu Mono',
       size: 14,
       weight: 'bold'
     }
  },
  labelPlacement: 'center-center',
  labelExpressionInfo: {
    expression: '$feature.totalAssets'
  },
  where: 'selected = 0',
};

export const selectedLabelClass = {  
  symbol: {
    type: 'text',
    yoffset: 1.5,
    size: 25, 
    color: 'white',
    font: {  
       family: 'Ubuntu Mono',
       size: 14,
       weight: 'bold'
     }
  },
  labelPlacement: 'center-center',
  labelExpressionInfo: {
    expression: '$feature.totalAssets'
  },
  where: 'selected = 1',
};

 

4.  I toggle the layers depending on the scale. The context for me telling you this is that when I remove the updated layer and then add it back on, the changes have occurred. 

 

 

 this.view.watch('scale', (scale) => {
        scale < 73000
          ? this.removeAndReplaceCurrentLayer(sitesLayer, false)
          : this.removeAndReplaceCurrentLayer(assetClusterLayer, true);
      });

  private removeAndReplaceCurrentLayer(layer: __esri.FeatureLayer, shouldBeClustered: boolean): void {
    if (this.isMapClustered() && !shouldBeClustered) {
      this.toggleClustered(false);
      this.view.map.layers.removeAll();
      this.currentLayer = layer;
      this.view.map.add(layer);
      layer
        .when()
        .then(async () => {
          this.layerView = await this.view.whenLayerView(layer);
        });
    }

    if (!this.isMapClustered() && shouldBeClustered) {
      this.toggleClustered(true);
      this.view.map.layers.removeAll();
      this.currentLayer = layer;
      this.view.map.add(layer);
      layer
        .when()
        .then(async () => {
          this.layerView = await this.view.whenLayerView(layer);
        });
    }
  }

 

I've tried calling refresh on every layer I can find, and none of it is working. That being said, I feel like there must some way to sync this up immediately. I just don't know how! 

Any ideas?

1 Solution

Accepted Solutions
rogenjh
New Contributor III

One last note here: 

I dropped the version down to 4.16 and the initial code worked just fine with updating the labels and the symbol. I think there is an issue beginning at 4.17 that has carried over to 4.18. For the time being, the above solution is a workaround, but non-ideal.

View solution in original post

0 Kudos
3 Replies
rogenjh
New Contributor III

I'll update my own post here, but the solution is not complete. I'm now running a refresh on the layer, but the refresh is only working after a delay between load and then another delay between clicking on the graphic. It seems to me that there is some sort of debounce time on refresh, but I haven't been able to set it.

 watchUtils.whenDefined(this.view.popup'selectedFeature'(selectedFeature__esri.Graphic=> {
        if (selectedFeature) {
          selectedFeature.setAttribute('selected'1)
          this.currentLayer.applyEdits({updateFeatures: [selectedFeature]})
          .then((res=> {
            this.currentLayer.when((layer=> {
              layer.refresh();
            });
          });
        }}
      );

 

0 Kudos
rogenjh
New Contributor III

Okay, so I will update again just in case anyone happens across this and has the same question or can help to explain the behavior of ESRI. I'm actually wondering if there isn't some sort of bug happening here, but I'm a bit too new to really claim that. 

Previously, I was attempting to update my queries. It was 'kind of' working excepting that my labels weren't behaving and changing colors with the changing attribute. The 'solution' is to actually remove the graphic and add a new graphic, which ESRI seems to like in terms of updating the label colors. 

For me, it's a pretty non-ideal solution because a doubled label appears before the proper label, probably as ESRI processes an add and then a delete. But for now, it will behave. 

  features.forEach(graphic => {
    if (graphic.getAttribute('selected') === 0) {
      const cloned: __esri.Graphic = graphic.clone();
      cloned.setAttribute('selected', 1);
      deleteFeatures.push(graphic);
      addFeatures.push(cloned);
    }
  });
  const result = await this.currentLayer.applyEdits({deleteFeatures, addFeatures});

 

 

 

0 Kudos
rogenjh
New Contributor III

One last note here: 

I dropped the version down to 4.16 and the initial code worked just fine with updating the labels and the symbol. I think there is an issue beginning at 4.17 that has carried over to 4.18. For the time being, the above solution is a workaround, but non-ideal.

0 Kudos