FeatureLayer setSelection puts outline underneath feature layer?

2724
2
05-14-2014 10:57 AM
by Anonymous User
Not applicable
Original User: sarahclark

I am working with dgrid to show attributes for a polygon feature layer, and when a row is clicked, highlight that polygon (from this sample). I want to mimic the style of ArcMap where an aqua-colored outline highlights the selected feature.

symbol:
fl = new FeatureLayer(...);

fl.on("load", function() {
         aqua = "00FFFF";
          lineAqua = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,aqua,3);
          fl.setSelectionSymbol(new SimpleFillSymbol().setOutline(lineAqua).setStyle(SimpleFillSymbol.STYLE_NULL));
          });


Selection function:
// fires when a row in the dgrid is clicked
          function selectState(e) {
            // select the feature
            var fl = map.getLayer("land");
            var query = new Query();
            query.objectIds = [parseInt(e.target.innerHTML)];
            fl.selectFeatures(query, FeatureLayer.SELECTION_NEW, function(result) {
              if ( result.length ) {
                // re-center the map to the selected feature
                map.centerAt(result[0].geometry.getExtent().getCenter());
              } else {
                console.log("Feature Layer query returned no features... ", result);
              }
            });
          }


However sometimes it is putting the SimpleFillSymbol below the feature layer, so that when a polygon is selected the outline is hidden... if I click a different  row, then click the same one, sometimes it draws one edge above the feature layer and the other 3 below...is there a way to force the order?

[ATTACH=CONFIG]33823[/ATTACH]
0 Kudos
2 Replies
KenBuja
MVP Esteemed Contributor
Hi Sarah,

I'm not sure if this will help, but I went a different route with highlighting a feature from a clicked row in a dGrid.

I didn't use a FeatureLayer, but a regular ArcGISDynamicMapServiceLayer along with a GraphicLayer. In my application, when the user click on a feature (or group of features), I get the list of returned features from an IdentifyTask. These get added to a GraphicsLayer and are used to populate a dGrid that resides in a TabContainer. If more than one layer is turned on in the TOC, then the results from each layer will be put into a separate dGrid.

identifyTask.execute(identifyParams, function (results) { populateTC(results, evt); });

    function populateTC(results, evt) {
        try {
            if (dijit.byId('tabs').hasChildren) {
                dijit.byId('tabs').destroyDescendants();
            }

            if (results.length === 0) {
                console.log('Nothing found.');
                return;
            }

            var combineResults = {};
            for (var i = 0, len = results.length; i < len; i++) {
                var result = results;
                var feature = result.feature;
                var lyrName = result.layerName.replace(' ', '');
                if (combineResults.hasOwnProperty(lyrName)) {
                    combineResults[lyrName].push(result);
                }
                else {
                    combineResults[lyrName] = [result];
                }
                switch (feature.geometry.type) {
                    case "point": case "multipoint":
                        layerResultsGraphic.add(new esri.Graphic(feature.geometry, symbolResultPoint, feature.attributes));
                        break;
                    case "polyline":
                        layerResultsGraphic.add(new esri.Graphic(feature.geometry, symbolResultPolyline, feature.attributes));
                        break;
                    case "polygon": case "extent":
                        layerResultsGraphic.add(new esri.Graphic(feature.geometry, symbolResultPolygon, feature.attributes));
                        break;
                }
            }

            for (result in combineResults) {
                if (combineResults.hasOwnProperty(result)) {

                    var columns = buildColumns(combineResults[result][0].feature);
                    var features = [];

                    for (i = 0, len = combineResults[result].length; i < len; i++) {
                        features.push(combineResults[result].feature);
                    }

                    var data = array.map(features, function (feature) {
                        return lang.clone(feature.attributes);
                    });

                    var dataGrid = new (declare([Grid, Selection, DijitRegistry, ColumnHider]))({
                        id: "dgrid_" + combineResults[result][0].layerId,
                        bufferRows: Infinity,
                        columns: columns,
                        selectionMode: "single",
                        "class": "resultsGrid"
                    });

                    var gridWidth = "width: " + String(columns.length * 100) + "px";
                    dataGrid.addCssRule("#" + dataGrid.id, gridWidth);

                    dataGrid.on(".dgrid-row:click", gridSelect);
                    dataGrid.on("show", function () {
                        dataGrid.resize();
                    });
                    dataGrid.on(mouseUtil.enterRow, gridEnter);
                    dataGrid.on(mouseUtil.leaveRow, function () {
                        map.graphics.clear();
                    });
                    var plural = "";
                    if (combineResults[result].length !== 1) { plural = "s"; }
                    var cp = new dijit.layout.ContentPane({
                        id: result,
                        //content: "<strong>" + combineResults[result][0].layerName + "</strong> (" + combineResults[result].length + " feature" + plural + ")",
                        content: combineResults[result].length + " feature" + plural,
                        //content: dataGrid,
                        title: combineResults[result][0].layerName,
                        style: "overflow: auto"
                    }).placeAt(dijit.byId('tabs'));

                    cp.addChild(dataGrid);
                    cp.startup();

                    dataGrid.renderArray(data);
                }
            }
            tc.startup();
            tc.resize();
            map.infoWindow.show(evt.screenPoint, map.getInfoWindowAnchor(evt.screenPoint));
        }
        catch (e) { console.log(e.message); }
    }


When the user moves the mouse over one of the rows in the dGrid, I search the GraphicsLayer for the correct feature and add that graphic to the map.graphics layer. If the use clicks on the row, I use the same logic to "flash" the feature.

    function gridEnter(e) {
        map.graphics.clear();

        var gridId = e.currentTarget.id;
        var selectedGrid = dijit.byId(gridId);

        var row = selectedGrid.row(e);

        graphicHighlight = findGraphicByAttribute(row.data);
        if (graphicHighlight !== null) {
            switch (graphicHighlight.geometry.type) {
                case "point": case "multipoint":
                    map.graphics.add(new esri.Graphic(graphicHighlight.geometry, symbolHighlightPoint));
                    break;
                case "polyline":
                    map.graphics.add(new esri.Graphic(graphicHighlight.geometry, symbolHighlightPolyline));
                    break;
                case "polygon": case "extent":
                    map.graphics.add(new esri.Graphic(graphicHighlight.geometry, symbolHighlightPolygon));
                    break;
            }
        }
    }

    function gridSelect(e) {
        var graphicFlash;
        var gridId = e.currentTarget.id;
        var selectedGrid = dijit.byId(gridId);
        var row = selectedGrid.row(e);

        graphicHighlight = findGraphicByAttribute(row.data);

        if (graphicHighlight !== null) {
            switch (graphicHighlight.geometry.type) {
                case "point": case "multipoint":
                    graphicFlash = new esri.Graphic(graphicHighlight.geometry, symbolFlashPoint)
                    break;
                case "polyline":
                    graphicFlash = new esri.Graphic(graphicHighlight.geometry, symbolFlashPolyline);
                    break;
                case "polygon": case "extent":
                    graphicFlash = new esri.Graphic(graphicHighlight.geometry, symbolFlashPolygon);
                    break;
            }
            map.graphics.add(graphicFlash);
        }

        var shape = graphicFlash.getDojoShape();
        var animStroke = fx.animateStroke({
            shape: shape,
            duration: 500,
            color: { end: new dojo.Color([0, 0, 0, 0]) }
        });
        var animFill = fx.animateFill({
            shape: shape,
            duration: 500,
            color: { end: new dojo.Color([0, 0, 0, 0]) }
        });
        var anim = dojo.fx.combine([animStroke, animFill]).play();
        var animConnect = dojo.connect(anim, "onEnd", function () {
            map.graphics.remove(graphicFlash);
        });
    }

    function findGraphicByAttribute(attributes) {

        for (i = 0; i < layerResultsGraphic.graphics.length; i++) {
            if (JSON.stringify(layerResultsGraphic.graphics.attributes) === JSON.stringify(attributes)) { return layerResultsGraphic.graphics; }
        }
        return null;
    }


Since the map.graphics layer is always on top of all other layers (including other GraphicsLayers), I never have to worry about the order.
0 Kudos
DavidWilton
Occasional Contributor

I just ran across the same issue. The problem with feature layer selections is that the don't add a new graphic, but change the symbology of the actual feature layer. Therefore the order is the same as the underlying feature layer. This is the same reason you can't do an arcMap style highlight the outline in cyan. Here is some pseudo code which shows how you could do it:

//don't do this. leave it is blank

//this.featureLayer().setSelectionSymbol(fmySelectionSymbol);

//do this instead

this.featureLayer.on('selection-complete', lang.hitch(this, this.featureLayerHighlightSelectedFeatures))

//mouse over event of grid row

onMouseOver(evt){

//get the oid From the row

var queryTask = new QueryTask(window.location.protocol + this.config.fieldsLayerUrl);

var query = new Query();

query.objectIds = oid;

this.featureLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW);

}

featureLayerHighlightSelectedFeatures: function(evt){

   //clear map graphics

   //loop through the graphics in the evt and add to map

}

0 Kudos