Show GIS attributes using QueryTask, FindTask and IdentifyTask

1677
7
Jump to solution
09-04-2014 03:29 PM
BhavinSanghani
Occasional Contributor II

I need to show GIS attribute values in tree view following way in for the UCs mentioned below:

-LayerName

           - FeatureID

                    - Feature Attributes

           - FeatureID

                    - Feature Attributes

-LayerName

           - FeatureID

                    - Feature Attributes

           - FeatureID

                    - Feature Attributes

Use cases:

1) If user passes single/multiple objectIds then search these values in all layers and show the layer and attributes in treeview

2) If user clicks on the map then search mappoint geometry to find gis attributes in visible layers and show the treeview

For # 1 - there are two scenarios

a) single objectId - I can use FindTask or QueryTask

b) multiple objectIds - I can use QueryTask

For # 2 - I can use IdentifyTask

Questions:

i) Is there any generic way to cover all these scenarios using same code?

ii) QueryTask doesn't return layerName when you query it  to multiple layers and fetching results in dojo/promise/all. What could be the solution in case of fetching attributes of multiple objectIds with layerName in results?

iii) FindTask or QueryTask - which one is better? FindTask doesn't allow to search text for multiple ids and QueryTask doesn't give layerName in the result when querying to multiple layers.

0 Kudos
1 Solution

Accepted Solutions
KenBuja
MVP Esteemed Contributor

However, the sample does contain this comment

          // results from deferred lists are returned in the order they were created
         
// so parcel results are first in the array and buildings results are second

And the documentation for dojo/promise/all says

Usage is straight forward, in that dojo/promise/all is a single argument that is either an Object or an Array. The results are either returned as an Object that uses the same keys as supplied in the argument or an Array in the same order that the supplied one:

View solution in original post

0 Kudos
7 Replies
KenBuja
MVP Esteemed Contributor

This is the way I add the layer name (and service URL) to my IdentifyTask results for multiple services

function runIdentifies(evt) {

    var idPoint = evt.mapPoint;

    var layers = arrayUtils.map(map.layerIds, function (layerId) {

        return map.getLayer(layerId);

    });

    //this filters out the basemaps and layers with no visible layers

    layers = arrayUtils.filter(layers, function (layer) {

        if (layer.visibleLayers !== undefined) {

            if (layer.visibleLayers[0] !== -1) {

                return layer.getImageUrl && layer.visible;

            }

        }

    });

    var params = createIdentifyParams(layers, evt);

    var tasks = arrayUtils.map(layers, function (layer) {

        return new IdentifyTask(layer.url);

    });

    var defTasks = arrayUtils.map(tasks, function (task) {

        return new Deferred();

    });

    var promises = [];

    for (var i = 0; i < tasks.length; i++) {

        promises.push(tasks.execute(params));

    }

    var allPromises = new all(promises);

    allPromises.then(function (r) { showIdentifyResults(r, tasks, idPoint); });

}

function createIdentifyParams(layers, evt) {

    var identifyParamsList = [];

    arrayUtils.forEach(layers, function (layer) {

        var idParams = new IdentifyParameters();

        idParams.width = map.width;

        idParams.height = map.height;

        idParams.geometry = evt.mapPoint;

        idParams.mapExtent = map.extent;

        idParams.layerOption = IdentifyParameters.LAYER_OPTION_VISIBLE;

        idParams.layerIds = layer.visibleLayers;

        idParams.tolerance = 3;

        idParams.returnGeometry = true;

        idParams.spatialReference = map.spatialReference;

        identifyParamsList.push(idParams);

    });

    return identifyParamsList;

}

function showIdentifyResults(r, tasks, idPoint) {

    var results = [];

    var taskUrls = [];

    r = arrayUtils.filter(r, function (results) {

        return r[0];

    });

    for (var i = 0; i < r.length; i++) {

        results = results.concat(r);

        for (var j = 0; j < r.length; j++) {

            taskUrls = taskUrls.concat(tasks.url);

        }

    }

    var formatResults = arrayUtils.map(results, function (result, index) {

        var feature = result.feature;

        //this adds new attributes to the feature for the layerName and service URL

        feature.attributes.layerName = result.layerName;

        feature.attributes.taskUrl = taskUrls[index];

        return feature;

    });

    if (formatResults.length > 0) {

    //this is a separate function to put the results into a TabContainer with each service on its own tab

       if (buildTabContainer(formatResults)) {

            map.infoWindow.show(idPoint);

        }

    }

}

Please remember to start discussions about the Javascript API in that space. It will help others when searching on this issue. You should move this discussion over there.

0 Kudos
BhavinSanghani
Occasional Contributor II

Hi Ken

1) How do I move this thread to ArcGIS JS API space? I don't see any link/button like 'move'.

2) The example you gave is related to IdentifyTask and that returns layername in the result. But QueryTask does't return layername similar way. Is that the design issue at API level? Is there any way to get layerName in the result of QueryTask when sending single query to multiple layers?

0 Kudos
KenBuja
MVP Esteemed Contributor

You should see the Move link in the Actions section as highlighted in the image below

geonet.png

0 Kudos
KenBuja
MVP Esteemed Contributor

Remember, you're explicitly setting which layer you're querying when assigning a URL to the QueryTask.

Take a look at this sample that shows how to show the results from querying several different layers.

0 Kudos
BhavinSanghani
Occasional Contributor II

In given example, it assumes the order of the request will be same in callback function results. Is that correct? Since requests are asynchronous, I guess order of the request will not be always same in the results. That means, results[0] may be buildings and results[1] may be parcels in this example.

0 Kudos
KenBuja
MVP Esteemed Contributor

However, the sample does contain this comment

          // results from deferred lists are returned in the order they were created
         
// so parcel results are first in the array and buildings results are second

And the documentation for dojo/promise/all says

Usage is straight forward, in that dojo/promise/all is a single argument that is either an Object or an Array. The results are either returned as an Object that uses the same keys as supplied in the argument or an Array in the same order that the supplied one:

0 Kudos
BhavinSanghani
Occasional Contributor II

Ok, that makes sense!  Thanks a lot for pointers!

0 Kudos