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
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.
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.
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;
});
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.
})));