Modify Renderer of FeatureLayer

5200
6
Jump to solution
04-02-2015 03:14 PM
AndyWright
Occasional Contributor

I am trying to modify the renderer on a FeatureLayer from a local geodatabase and have not had much success.  I can see my modifications to the renderer when I console.log its json, but the changes do not get applied to the layer in the map.  FeatureLayer does not have a refresh like dynamic map layers do, so I'm not sure how to update the layer in the map so it reflects the changes I made to the renderer.   I have included my code below.  Does anyone have any ideas?

import QtQuick 2.3

import QtQuick.Controls 1.2

import ArcGIS.Runtime 10.25

import ArcGIS.Extras 1.0

ApplicationWindow {

    id: appWindow

    width: 800

    height: 600

    title: "SmallSymbolFix"

    property string m_LocalDataPath: System.userHomeFolder.path + "/Documents"

    Map {

        id: appMap

        anchors.fill: parent

        wrapAroundEnabled: true

        ArcGISTiledMapServiceLayer {

            url: "http://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer"

        }

        onStatusChanged: {

           if (status === Enums.MapStatusReady)

              damageGdb.path = m_LocalDataPath + "/EpochField/Data/DamageAssessment/WorkAssignments.geodatabase"

        }

        FeatureLayer {

            id: featLyr

            featureTable: featTab

            onStatusChanged: {

                if (status === Enums.LayerStatusInitialized) {

                    var newRenderer = ArcGISRuntime.createObject("UniqueValueRenderer");

                    var oldRenderer = featLyr.renderer;

                    for (var l = 0; l < oldRenderer.uniqueValues.length; ++l) {

                        var newSym = ArcGISRuntime.createObject("PictureMarkerSymbol");

                        newSym = oldRenderer.uniqueValues.symbol

                        newSym.height = 40;

                        newSym.width = 40;

                        var newUVI = ArcGISRuntime.createObject("UniqueValueInfo");

                        newUVI = oldRenderer.uniqueValues;

                        newUVI.symbol = newSym;

                        //console.log("\n\nNEW SYMBOL: " + JSON.stringify(newSym.json));

                        newRenderer.addValue(newUVI);

                    }

                    featLyr.renderer = newRenderer;

                    console.log("\n\nNEW RENDERER: " + JSON.stringify(newRenderer.json));

                }

            }

        }

    }

    Geodatabase {

        id: damageGdb

        onValidChanged: {

            if (valid) {

                //  Add feature layer to map

                var gdbFeatTab = geodatabaseFeatureTable("Work Assignment");

                var operLayer = ArcGISRuntime.createObject("FeatureLayer");

                operLayer.featureTable = gdbFeatTab;

                appMap.addLayer(operLayer);

            }

        }

    }

    GeodatabaseFeatureTable {

        id: featTab

        geodatabase: damageGdb.valid ? damageGdb : null

        featureServiceLayerName: "Work Assignment"

        onGeodatabaseFeatureTableValidChanged: {

            if (geodatabaseFeatureTableValid) {

                console.log("Work Assignment feature table is initialized ...")

            }

        }

    }

}

0 Kudos
1 Solution

Accepted Solutions
LucasDanzinger
Esri Frequent Contributor

Hey Andy,

Yes, that should work as well. I think the main issue with your code is that you aren't setting the attributeNames on the feature layer's new renderer. Check out the example below and see if you can get that working in your app.

-Luke

import QtQuick 2.3
import QtQuick.Controls 1.2
import ArcGIS.Runtime 10.25
import ArcGIS.Extras 1.0




ApplicationWindow {
    id: appWindow
    width: 800
    height: 600
    title: "SmallSymbolFix"




    Map {
        id: appMap
        anchors.fill: parent


        ArcGISTiledMapServiceLayer {
            url: "http://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer"
        }


        FeatureLayer {
            id: featLyr
            featureTable: featureServiceTable
        }
    }


    Button {
        anchors {
            left: parent.left
            top: parent.top
            margins: 15
        }
        text: "change renderer"
        onClicked: {
            var orig_info_List = featLyr.renderer.uniqueValues;
            var new_renderer = ArcGISRuntime.createObject("UniqueValueRenderer", {attributeNames: featLyr.renderer.attributeNames});
            for (var i = 0; i < orig_info_List.length; ++i) {
                //create the new symbol
                var symbol = orig_info_List.symbol;
                symbol.width = 40;
                symbol.height = 40;
                //create the new UniqueValueInfo
                var newInfo = ArcGISRuntime.createObject("UniqueValueInfo");
                newInfo = orig_info_List;
                newInfo.symbol = symbol;
                new_renderer.addValue(newInfo);
            }
            featLyr.renderer = new_renderer;
        }
    }




    GeodatabaseFeatureServiceTable {
        id: featureServiceTable
        url: "http://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/FeatureServer/0"
    }
}




















View solution in original post

0 Kudos
6 Replies
LucasDanzinger
Esri Frequent Contributor

Hey Andy-

In general, it can be done. Here is a simplified version of your code that uses the DamageInpsection geodatabase that comes with the sdk. I can switch it over to use a simple marker symbol.

import QtQuick 2.3
import QtQuick.Controls 1.2
import ArcGIS.Runtime 10.25
import ArcGIS.Extras 1.0




ApplicationWindow {
    id: appWindow
    width: 800
    height: 600
    title: "SmallSymbolFix"


    Map {
        id: appMap
        anchors.fill: parent
        wrapAroundEnabled: true


        ArcGISTiledMapServiceLayer {
            url: "http://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer"
        }


        FeatureLayer {
            id: featLyr
            featureTable: featTab
        }
    }


    Button {
        anchors {
            left: parent.left
            top: parent.top
            margins: 15
        }
        text: "change renderer"
        onClicked: {
            var newRenderer = ArcGISRuntime.createObject("SimpleRenderer");
            newRenderer.symbol = ArcGISRuntime.createObject("SimpleMarkerSymbol", {color: "blue", size: 25});
            featLyr.renderer = newRenderer;
        }
    }


    Geodatabase {
        id: damageGdb
        path: "C:/temp/DamageInspection6.geodatabase"
    }


    GeodatabaseFeatureTable {
        id: featTab
        geodatabase: damageGdb
        featureServiceLayerId: 0
    }
}















0 Kudos
AndyWright
Occasional Contributor

HI Lucas,

Thanks for the reply.  When you say in general does that mean it can only be done for simple renderers?  Can I do this with unique value renderers?  Can I modify the layer's existing renderer or does it just work when you create something from scratch? 

I feel like I'm very close as I can see my symbol modifications in the json for the new renderer, I just can't figure out how to apply that new renderer to the feature layer.

0 Kudos
LucasDanzinger
Esri Frequent Contributor

Hey Andy,

Yes, that should work as well. I think the main issue with your code is that you aren't setting the attributeNames on the feature layer's new renderer. Check out the example below and see if you can get that working in your app.

-Luke

import QtQuick 2.3
import QtQuick.Controls 1.2
import ArcGIS.Runtime 10.25
import ArcGIS.Extras 1.0




ApplicationWindow {
    id: appWindow
    width: 800
    height: 600
    title: "SmallSymbolFix"




    Map {
        id: appMap
        anchors.fill: parent


        ArcGISTiledMapServiceLayer {
            url: "http://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer"
        }


        FeatureLayer {
            id: featLyr
            featureTable: featureServiceTable
        }
    }


    Button {
        anchors {
            left: parent.left
            top: parent.top
            margins: 15
        }
        text: "change renderer"
        onClicked: {
            var orig_info_List = featLyr.renderer.uniqueValues;
            var new_renderer = ArcGISRuntime.createObject("UniqueValueRenderer", {attributeNames: featLyr.renderer.attributeNames});
            for (var i = 0; i < orig_info_List.length; ++i) {
                //create the new symbol
                var symbol = orig_info_List.symbol;
                symbol.width = 40;
                symbol.height = 40;
                //create the new UniqueValueInfo
                var newInfo = ArcGISRuntime.createObject("UniqueValueInfo");
                newInfo = orig_info_List;
                newInfo.symbol = symbol;
                new_renderer.addValue(newInfo);
            }
            featLyr.renderer = new_renderer;
        }
    }




    GeodatabaseFeatureServiceTable {
        id: featureServiceTable
        url: "http://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/FeatureServer/0"
    }
}




















0 Kudos
AndyWright
Occasional Contributor

The attributeNames property was the missing piece.  Thanks for your help Lucas!

0 Kudos
albavoli
New Contributor III

i am using the same example but instead of a simple mark symbol i wanna add a picture one but doesnt refrect on the layer it just shows a red circle marker not the image :

   var newRenderer = ArcGISRuntime.createObject("SimpleRenderer");

    newRenderer.symbol = ArcGISRuntime.createObject("PictureMarkerSymbol", {url: "RedShinyPin.png"});
  layer.renderer = newRenderer;
what might be the problem?
0 Kudos
LucasDanzinger
Esri Frequent Contributor

The code looks fine and should work no problem. Maybe it can't find the PNG? Try giving it an online URL like this just to make sure that isn't the problem - http://static.arcgis.com/images/Symbols/AtoZ/redB.png

0 Kudos