Where to start, custom select, geoprocessing, or something else?

786
4
08-12-2019 03:25 AM
JamesHone1
New Contributor III

Hi I'm new to web app builder and finding it rather difficult to work out exactly what I need to do to achieve the behaviour I have in mind.

I want my users to draw an area, then that area is used to query and return a list of data that has been cropped to that area with some extra attributes showing % of features total area thats left etc . Users can then select which of these pieces of data they want to have in their resulting data set that will be purchased and downloaded.

I initially thought I would need to use the select widget then use the selection area to crop the selected data. The select widget is quite complex and I could not work out how to get it to return the limits of the selection along with the selected features so I can use it to clip them. 

The next option I am thinking may be a way to do this is a geo-processing widget, it says it can take drawing on the map as input, then I can use that input to crop and return the list of data for selection. I'm still waiting on come access to server so I haven't had chance to create the service and experiment with this yet.

Does this sound like I am going in the right direction to do it? I have limited time and need to focus my learning efforts in the correct place to achieve this. Should I be looking to modify the select widget, (looks difficult and I couldn't find any examples of similar being done) or setting up a geo-processing widget, or am I barking up the wrong tree and I should be doing something else?

Any help or links to resources that solve a similar problem is greatly appreciated.

Thanks

Jim

0 Kudos
4 Replies
JamesHone1
New Contributor III

It seems dojo tutorials were the best resource to understand this a bit more, after a few of those I'm finding the code easier to deal with. I'm currently thinking I need to use drawbox, this will pass its geometry to a query to select data, the data selected will be displayed in a list where the users can select what they wish to extract. This will then pass the drawbox geom with the user list to a geoprocess to clip and extract the data.

My main struggle now is working out how to select data, as I want the geom for another process I'm not sure the current select widget exposes the geom used for selection so I need to modify an existing select or create a new simpler select, probably without all the config.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

  Once you have the geometry from the DrawBox you just use a QueryTask and Query in your code to get the features the DrawBox Geometry intersects. This workflow is seen in many OTB widgets that you can borrow code from.

0 Kudos
JamesHone1
New Contributor III

Thanks robert, Ive currently had a go using the FeatureSetChooserFromMultipleLayers, I have passed layers in and I see the dijit, I can draw a box. The only problem I have is I don't know if I have actually selected anything or how to access them if I have.

As I had set 'updateSelection: true' I was expecting my map to change once the box was drawn and display the selected items. I have seem some examples using drawbox and query, I think I will start again trying that method ignoring the FeatureSetChooserForMultipleLayers as I have seen a nice example of that that I understand here.

I would still like to know if my code below is actually selecting features though, and if it is how do I access them?


define(['dojo/_base/declare',
'dijit/_WidgetsInTemplateMixin',
'jimu/BaseWidget',
'dojo/_base/html',
'dojo/_base/lang',
'dojo/on',
'esri/Color',
'esri/symbols/SimpleMarkerSymbol',
'esri/symbols/SimpleLineSymbol',
'esri/symbols/SimpleFillSymbol',
'jimu/dijit/FeatureSetChooserForMultipleLayers',
'jimu/LayerInfos/LayerInfos',
'jimu/LayerStructure',
'jimu/SelectionManager',
'dojo/_base/array',
'dojo/domReady!'

],
function(declare, _WidgetsInTemplateMixin, BaseWidget, html, lang, on, Color, SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol, 
 FeatureSetChooserForMultipleLayers, LayerInfos, LayerStructure, SelectionManager, array) {
  var clazz = declare([_WidgetsInTemplateMixin, BaseWidget], {
    baseClass: 'jimu-widget-jimwidget',

      //this property is set by the framework when widget is loaded.
      name: 'jimwidget',


      //methods to communication with app container:

      postCreate: function() {
        this.inherited(arguments);
        console.log('postCreate');
        
        //get the selection colour from config and use it to set default symbols.
        var selectionColor = new Color(this.config.selectionColor);
        this.defaultPointSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 16, null, selectionColor);
        this.defaultLineSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, selectionColor, 2);
        this.defaultFillSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,this.defaultLineSymbol, new Color([selectionColor.r, selectionColor.g, selectionColor.b, 0.3]));


        //get layer structure and use it to get a list of feature layers to pass into the selct dijit
        var layerStructure = new LayerStructure.getInstance();
        // this._printLayerTree(layerStructure);

        //get list of feature layers
        featureLayers = this._getFeatureLayers(layerStructure);

        // create select dijit
        this.selectDijit = new FeatureSetChooserForMultipleLayers({
          map: this.map,
          updateSelection: true,
          fullyWithin: this.config.selectionMode === 'wholly',
          geoTypes: this.config.geometryTypes || ['EXTENT']
        });

        this.selectDijit.setFeatureLayers(featureLayers);

        html.place(this.selectDijit.domNode, this.selectDijitNode);
        this.selectDijit.startup();

        //attach a function to the use-clear button, currently just prints to console.
        this.own(on(this.selectDijit, 'user-clear', lang.hitch(this, this._clearAllSelections)));
        
        //just copy pasted these two this.own, not sure on em yet
        // this.own(on(this.selectDijit, 'loading', lang.hitch(this, function() {
        //   this.shelter.show();
        // })));
        // this.own(on(this.selectDijit, 'unloading', lang.hitch(this, function() {
        //   this.shelter.hide();
        // })));
      },

      startup: function() {
        this.inherited(arguments);
        console.log('startup');
      },

      _clearAllSelections: function() {
        console.log("Clear selections");
      },

      //example of using traversal in layer structure to print layers to console
      _printLayerTree: function(layerStructure) {
        layerStructure.traversal(function(layerNode) {
          //nest 3 lines pring the layer to console with nice indent loop
          var indent = "";
          for(var i = 0; i < layerNode.getNodeLevel(); i++) {indent += "  ";}
          console.log(indent, layerNode.title + '  :  ' + layerNode.type);
        });
      },

      _getFeatureLayers: function(layerStructure) {
      	
        //init the array to return
        var layerArray = [];

        //traverse throught he layerstructure passed in adding feature layers to the array
      	layerStructure.traversal(function(layerNode) {
          layerNode.getLayerType().then(function(ltype){
            if (ltype == 'FeatureLayer'){
              layerArray.push(layerNode.getLayerObject())
            }
          });
        });
      	return layerArray
      },
  });
return clazz;
});‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

James,

 Your code looks fine. You should check the featurelayers for a selection.

              // On selection complete
              this.own(on(this.selectDijit, 'unloading', lang.hitch(this, function () {
                var selectedFeatures = [];
                array.forEach(featureLayers, lang.hitch(this, function (layer) {
                  selectedFeatures = selectedFeatures.concat(layer.getSelectedFeatures());
                }));
                this.selectedFeatureGeoms = array.map(selectedFeatures, function (feature) {
                  return feature.geometry;
                });
                //now do something with the selectedFeatureGeoms array.
              })));‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos