FeatureLayer Renderer Based on External Attributes

761
2
03-26-2019 01:17 PM
by Anonymous User
Not applicable

Greetings, 

I am trying to combine information from an ArcGIS Server feature layer with attributes from a Salesforce database in a feature layer in a Javascript application. I would like to be able to load a featurelayer into a map application and update the rendere based on attributes that I gather from Salesforce.

My thinking was that I could use the MapView.whenLayerView to get a list of the features within the MapView.extent. Each time the MapView extent changes I could use LayerView.queryFeatures to loop over each graphic, append an attribute to the graphic and then set the symbol of the graphic. 

Unfortunately this does not seem to work. Am I doing this wrong? Can this even be done?

Thanks, Tyler 

loadFeatureLayers = (mapView) => {
    const self = this
    loadModules(['esri/layers/FeatureLayer'])
    .then(([FeatureLayer]) => 
    {
      layers.forEach(function(layer){
        let fl = new FeatureLayer({
            url: layer.url + layer.serviceIndex
            , baseUrl : layer.url
            , serviceIndex : layer.serviceIndex
            , outFields: ["*"]
            , popupTemplate: layer.popupTemplate
            , definitionExpression: layer.definitionExpression
        });
        fl.minScale = layer.minScale;
        fl.renderer = layer.classrenderer
        fl.when(function(featureLayer){
          featureLayer.id = layer.id;
          let layersConcat = self.state.layers.concat({'featureLayerId' : featureLayer.id, 'identifyable' : true})
          self.setState({layers: layersConcat})
        });
        //fl.renderer = layer.renderer
        mapView.map.add(fl)
        mapView.whenLayerView(fl).then(function(layerView) {
          layerView.watch("updating", function(value) {
            if (!value) { // wait for the layer view to finish updating
              // query all the features available for drawing.
              const adoptedSymbol = {
                "type": "simple-marker"  // autocasts as new SimpleMarkerSymbol()
                , "size": 12
                , "color": "red"
                , "outline": {  // autocasts as new SimpleLineSymbol()
                    "width": 0.5
                    , "color": "white"
                }
              }
              const unadoptedSymbol = {
                "type": "simple-marker"  // autocasts as new SimpleMarkerSymbol()
                , "size": 12
                , "color": "blue"
                , "outline": {  // autocasts as new SimpleLineSymbol()
                    "width": 0.3
                    , "color": "white"
                }
              }
              layerView.queryFeatures({
                geometry: mapView.extent,
                returnGeometry: true,
                outFields: ["*"]
              }).then(function(results) {
                let graphics = results.features;
                let testVal = false;
                let flGraphics = []
                graphics.forEach(function(g, index) {
                  let graphic = JSON.parse(JSON.stringify(g))
                  graphic.geometry.type = "point"
                  let attributes = graphic.attributes
                  testVal = !testVal
                  testVal === true ? graphic.symbol = adoptedSymbol:graphic.symbol = unadoptedSymbol
                  attributes.test =  testVal
                  graphic.attributes = attributes
                  flGraphics.push(graphic)
                });
                fl.source = flGraphics
                //fl.refresh()
              }).catch(function(error) {
                console.error("query failed: ", error);
              });
            }
          });
        });
      })
    })
  }
Tags (2)
0 Kudos
2 Replies
JohnGrayson
Esri Regular Contributor

The 'source' property of the FeatureLayer is used as a constructor parameter when creating a new FeatureLayer from client-side graphics, but that is not your use case as your data comes from a url.  The way to control the rendering is via a Renderer and I would suggest you check out the use of Arcade to drive advanced visualizations as it might provide what you need.  The important part of this task is to establish a clear relationship between information that already exists in the attributes of the FeatureLayer and information from the external resource.  If you can express that relationship in Arcade, then you should be able to do what you need.

by Anonymous User
Not applicable

Hi John, 

Could I get a little more information form you. I have figured out how to do a simple Arcade renderer on my featureLayer's attributes. I can pull data from an auxiliary database. How do I join my data to my featureLayer so that I can apply the Arcade expression to it.

For instance if I pull a a STATUS field and an OBJECTID from a external database, how do I add the status field to the feature layer so that I can render the featureLayer on the STATUS field?

I'm pretty sure I can create a GraphicsLayer by querying my map service by my view extent and then build the GraphicsLayer on the fly (along with the auxiliary data attributes)  when the view extent changes.

I'd much rather work with a feature layer if there is any way to join attributes and render on the joined attributes. 

Thanks, Tyler 

0 Kudos