2

I am trying to build my first widget, for use in the Configurable Map Viewer (CMV), using code from ESRI's ArcGIS API for JavaScript feature layer with selection sample. I've been successful in configuring a template and css file so the select and clear buttons show up in the viewer as desired, but I am having trouble modifying the ESRI developer sample for use in the CMV. I've adapted enough of the sample to be able to draw a box on the map with the draw tool but nothing is selected. I'm not following enough of what's going on in some of the other widgets I've looked at to have any confidence that I've successfully adapted the code for PostCreate, initSelectToolbar or sumGasProduction (obviously I haven't). I'm wondering if anyone has tackled the ESRI sample and has any suggestion as to what PostCreate, initSelectToolbar and sumGasProduction should look like or have any suggested references for someone getting started?

Code:

define([
'dojo/_base/declare',
'dijit/_WidgetBase',
'dijit/_TemplatedMixin',
'dijit/_WidgetsInTemplateMixin',
'esri/toolbars/draw',
'esri/InfoTemplate',
'esri/layers/FeatureLayer',
'esri/symbols/SimpleFillSymbol',
'esri/symbols/SimpleLineSymbol',
'esri/Color',
'esri/tasks/query',
'dijit/form/Button',
'dojo/_base/lang',
'dojo/on',
'dojo/text!./Select/templates/Select.html',
'xstyle/css!./Select/css/Select.css'
], function (declare, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, Draw, InfoTemplate, FeatureLayer, SimpleFillSymbol, SimpleLineSymbol, Color, Query, Button, lang, on, SelectTemplate, css) {
return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
    widgetsInTemplate: true,
    templateString: SelectTemplate,
    selectTools: null,
    postCreate: function () {
        this.selectTools = new Draw(this.map);
        this.selectTools.on('load', lang.hitch(this, 'initSelectToolbar'));
        this.fieldsSelectionSymbol =
            new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
            new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
            new Color([255, 0, 0]), 2),
            new Color([255, 255, 0, 0.5]));

        var content = "<b>Status</b>: ${STATUS}" +
                        "<br><b>Cumulative Gas</b>: ${CUMM_GAS} MCF" +
                        "<br><b>Total Acres</b>: ${APPROXACRE}" +
                        "<br><b>Avg. Field Depth</b>: ${AVG_DEPTH} meters";

        var infoTemplate = new InfoTemplate("${FIELD_NAME}", content);

        this.featureLayer = new FeatureLayer("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Petroleum/KSPetro/MapServer/1",
        {
            mode: FeatureLayer.MODE_ONDEMAND,
            infoTemplate: infoTemplate,
            outFields: ["*"]
        });

        this.featureLayer.setDefinitionExpression("PROD_GAS='Yes'");
        this.featureLayer.setSelectionSymbol(this.fieldsSelectionSymbol);
        this.featureLayer.on("selection-complete", 'sumGasProduction');
        this.featureLayer.on("selection-clear", function () {
            document.getElementById('messages').innerHTML = "<i>No Selected Fields</i>";
        });

        this.map.addLayer(FeatureLayer);

    },

    select: function () {
        this.selectTools.activate(Draw.EXTENT);
    },
    clearSelection: function () {
        this.featureLayer.clearSelection();
    },


    initSelectToolbar: function (event) {
        //selectionToolbar = new Draw(event.map);
        this.selectQuery = new Query();

        on(this.selectTools, "DrawEnd", function (geometry) {
            this.selectTools.deactivate();
            this.selectQuery.geometry = geometry;
            this.featureLayer.selectFeatures(this.selectQuery,
            FeatureLayer.SELECTION_NEW);
        });
    },
    sumGasProduction: function (event) {
        this.productionSum = 0;
        //summarize the cumulative gas production to display
        arrayUtil.forEach(event.features, function (feature) {
            this.productionSum += feature.attributes.CUMM_GAS;
        });
        document.getElementById('messages').innerHTML = "<b>Selected Fields Production: " + productionSum + " mcf. </b>";
    }
});

});

3
  • If you post up your code you are having issues with, we may be able to help better. Try using jsfiddle.net too! Also, you may want to look into a JS debugger, which will help you track down the issues yourself.
    – janechii
    Sep 26, 2014 at 0:31
  • I've posted up what I have. I'm debugging in Visual Studio. Are there better tools for js debugging? Sep 26, 2014 at 4:39
  • About debugging, I find the best tool is walking through your javascript code using Chrome's Dev Tools.
    – tmcgee
    Sep 26, 2014 at 17:56

2 Answers 2

2

The following configuration below seems to be working fine. I'd appreciate any issues being pointed out.

The configuration of the widget:

select: {
                include: true,
                id: 'select',
                type: 'titlePane',
                canFloat: true,
                path: 'gis/dijit/Select',
                title: 'Select',
                open: false,
                position: 10,
                options: {
                    map: true,
                    mapClickMode: true,
                    featureLayerURL: 'http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Petroleum/KSPetro/MapServer/1',
                    content: "<b>Status</b>: ${STATUS}" +
                            "<br><b>Cumulative Gas</b>: ${CUMM_GAS} MCF" +
                            "<br><b>Total Acres</b>: ${APPROXACRE}" +
                            "<br><b>Avg. Field Depth</b>: ${AVG_DEPTH} meters",
                    title: '${FIELD_NAME}',
                    defExpress: "PROD_GAS='Yes'",
                    clearSelectMsg: 'No Selected Fields',
                    fieldToSum: 'CUMM_GAS',
                    selectSumMsgPrefix: 'Selected Fields Production:',
                    selectSumUnits: 'mcf'
                }
            },

The widget:

define([
'dojo/_base/declare',
'dijit/_WidgetBase',
'dijit/_TemplatedMixin',
'dijit/_WidgetsInTemplateMixin',
'esri/toolbars/draw',
'esri/InfoTemplate',
'esri/layers/FeatureLayer',
'esri/symbols/SimpleFillSymbol',
'esri/symbols/SimpleLineSymbol',
'esri/Color',
'esri/tasks/query',
'dijit/form/Button',
'dojo/_base/lang',
'dojo/on',
'dojo/_base/array',
'dojo/dom',
'dojo/text!./Select/templates/Select.html',
'xstyle/css!./Select/css/Select.css'
], function (declare, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, Draw, InfoTemplate, FeatureLayer, SimpleFillSymbol, SimpleLineSymbol, Color, Query, Button, lang, on, arrayUtil, dom, SelectTemplate, css) {
    return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
        widgetsInTemplate: true,
        templateString: SelectTemplate,
        selectTools: null,

        postCreate: function () {
            this.selectTools = new Draw(this.map);

            this.selectQuery = new Query();

            on(this.selectTools, "DrawEnd", lang.hitch(this, function (geometry) {
                this.selectTools.deactivate();
                this.selectQuery.geometry = geometry;
                this.featureLayer.selectFeatures(this.selectQuery,
                FeatureLayer.SELECTION_NEW);
            }));

            this.fieldsSelectionSymbol =
                new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
                new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
                new Color([255, 0, 0]), 2),
                new Color([255, 255, 0, 0.5]));


            var infoTemplate = new InfoTemplate(this.title, this.content);

            this.featureLayer = new FeatureLayer(this.featureLayerURL,
            {
                mode: FeatureLayer.MODE_ONDEMAND,
                infoTemplate: infoTemplate,
                outFields: ["*"]
            });

            this.featureLayer.setDefinitionExpression(this.defExpress);
            this.featureLayer.setSelectionSymbol(this.fieldsSelectionSymbol);
            this.featureLayer.on("selection-complete", lang.hitch(this, 'sumGasProduction'));
            var clearMsg = this.clearSelectMsg;
            this.featureLayer.on("selection-clear", function () {
                dom.byId('messages').innerHTML = "<i>" + clearMsg + "</i>";
            });

            this.map.addLayer(this.featureLayer);

        },

        select: function () {
            this.selectTools.activate(Draw.EXTENT);
        },
        clearSelection: function () {
            this.featureLayer.clearSelection();
        },


        sumGasProduction: function (event) {
                        var productionSum = 0;
                        var sumField = this.fieldToSum;

                        arrayUtil.forEach(event.features, function (feature) {
                            productionSum += feature.attributes[sumField];

                        });
                        dom.byId('messages').innerHTML = "<b>" + this.selectSumMsgPrefix + " " + productionSum + " " + this.selectSumUnits + ". </b>";
                    }
    });
});
1
  • If you want the code to work for future versions of arcgis jsapi, then I would probably change "DrawEnd" event to "draw-end" instead. Don't know when they'll drop the old event names. But glad you got it working!
    – janechii
    Oct 1, 2014 at 17:17
0

To really answer you question: The references I think would be the most useful for you are the Dojo's tutorials and ESRI JSAPI Reference. Please look over ALL of Dojo's tutorials. If you don't understand something there, you'll need to brush up on JavaScript. From there, I think adapting ESRI samples to CMV would be much easier for you :)

Specifically about your code, couple of things I see right away are:

Draw doesn’t have a load event, so your listener here is just not doing anything:

this.selectTools.on('load', lang.hitch(this, 'initSelectToolbar'));

Secondly, your DrawEnd listener is probably not scoped right. You're using this inside there without rescoping. Try:

    on(this.selectTools, "draw-end", lang.hitch(this, function (geometry) {
        this.selectTools.deactivate();
        this.selectQuery.geometry = geometry;
        this.featureLayer.selectFeatures(this.selectQuery,
        FeatureLayer.SELECTION_NEW);
    }));

Better yet, I would really just move the content of initSelectToolbar into your postCreate and get rid of your load listener altogether.

As for debugger, I would use whatever you're comfortable with. If you were to create breakpoints on the initSelectToolbar method, you'd probably notice that it never gets called.

Hope these were the only issues!

7
  • Just quickly reviewing your code. I believe that janechii's comment about scope in the on(this.selectTools... line is correct. If you change the scope, it should do the selection on the feature layer. Whether it will then call the sumGasProduction is the next step. That code appears correct but you can't tell for sure until after the selection works.
    – tmcgee
    Sep 26, 2014 at 17:54
  • I've taken @janechii advice and rolled initSelectToolbar into postCreate. I had to make a few other changes that I won't bother posting yet but I've got the selection working. sumGasProduction isn't quite there. I've changed arrayUtil to this.arrayUtil but the function throws Unable to get property 'forEach' of undefined or null reference. Thoughts on that one? Sep 26, 2014 at 19:51
  • that is a problem too, isn't it? the arrayUtil is referring to dojo's dojotoolkit.org/reference-guide/1.10/dojo/_base/array.html. You'll have to load that with the define. Sooo.... define([..., 'dojo/_base/array',...], function (..., arrayUtil,...) and take out the this you added.
    – janechii
    Sep 26, 2014 at 20:11
  • Also, i've updated my response to answer your question better!
    – janechii
    Sep 26, 2014 at 20:28
  • It wasn't a problem per se. That was the part of my "few other changes" I didn't bother posting. Your comment made me realize an obvious mistake. function (..., arrayUtil,...) <> function (..., array,...). I corrected that and it looks to be working fine. I'll post my working code on Monday. I appreciate the suggestions and links. They've been very helpful in moving me along. Sep 27, 2014 at 4:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.