9

I'm adding a Dynamic Map Service to an ArcGIS Server JavaScript API map, and I need to get hold of each component layer and its fields, so I can run a query.

See the sample ArcGIS Server services directory at http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/HomelandSecurity/operations/MapServer

If you open this URL in a browser you can see the list of available layers (0,1,2) and each layer's fields.

How can I retrieve the list of fields programatically, within a JavaScript function? The code snippet below shows how to retrieve the layer endpoints, but I can't see how to get to the fields.

(One option is to add the layers as Feature Layers, but I'd prefer to avoid this if possible).

var url = "http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/HomelandSecurity/operations/MapServer/";
var dynLayer = new esri.layers.ArcGISDynamicMapServiceLayer(url);
map.addLayer(dynLayer);

dojo.connect(dynLayer, "onLoad", function() {
   var infos = dynLayer.layerInfos;
   for (var i = 0; i <= infos.length - 1; i++) {
       var layerId = infos[i].id;
       var restEndPoint = url + layerId;
       //restEndPoint is the layer's URL - how can I retrieve its fields?
   }
});

Thanks, Steve (cross-posted to the ArcGIS Server forum)

2 Answers 2

6

Use esri.request() to hit each layer's REST endpoint to get info about fields. Here's a simple example:

<html>
  <head>
    <script type="text/javascript">var djConfig = {parseOnLoad: true};</script>
    <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.4"></script>
    <script type="text/javascript">
      dojo.require("esri.map");
      // var service_url = 'http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hurricanes/NOAA_Tracks_1851_2007/MapServer/layers';
      var service_url = 'http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Fire/Sheep/MapServer/layers';

      function init() {
        esri.request({
          url: service_url,
          content: { f: 'json' },
          callbackParamName: 'callback',
          load: processServiceInfo,
          error: errorHandler
        });
      }
      // Runs once
      function processServiceInfo(info) {
        console.log('svc info: ', info);
        dojo.byId('info').innerHTML = '';
        dojo.forEach(info.layers, function(lyr) {

          // Add a new div for each Layer
          var lyr_div = dojo.create('div', { 
            id: 'layer_' + lyr.id,
            innerHTML: '<strong>Layer: ' + lyr.name + '</strong><br />'
          }, dojo.byId('info'));

          dojo.forEach(lyr.fields, function(field) {
            lyr_div.innerHTML += 'Name: ' + field.name + '; Alias: ' + field.alias + '<br />';
          });
        });
      }

      function errorHandler(err) {
        console.log('error: ', err);
      }

      dojo.ready(init);
    </script>
  </head>
  <body>
    <div id="info">field names and aliases will show up here.</div>
  </body>
</html>

That code uses v2.0 of the API but the same thing will work at 2.3 or 2.4. I originally posted in the Esri JS API forum.

Edit: Updated to handle all layers in a service. The code also now uses version 2.4 of the API.

5
  • +1 Looks good. Since user has 3 layers though, maybe having init call a FieldsInit function for each layer might be more useful. Aug 16, 2011 at 14:20
  • esri.request is the way to go, but instead of querying individual layers, just query them all at once by using http://..../MapServer/layers?f=json as the URL. Aug 16, 2011 at 14:54
  • Between you all, I think we have a great answer :) @Derek can you edit the code to handle all layers as per Sasa's suggestion, and I'll mark it as accepted? Thanks everyone Aug 16, 2011 at 21:01
  • There ya go Steve...updated my code sample to provide info for all layers in a map service. Aug 16, 2011 at 22:55
  • Thanks. I'm loading the JSON result into a global variable which I can then access at any time, to determine the layers and fields available in the map. Brilliant. Aug 17, 2011 at 1:19
0

I may have the wrong end of the stick here, but don't you just perform a query on the layer in question and get the results back as a resultset? If you ask for it in json, you can parse the results?

So for this:

http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer/1/query?where=STATE_NAME%3D%27Florida%27&f=json

The return is:

{"displayFieldName":"STATE_NAME","fieldAliases":{"STATE_NAME":"STATE_NAME"},"geometryType":"esriGeometryPolygon","spatialReference":{"wkid":4326},"fields":[{"name":"STATE_NAME","type":"esriFieldTypeString","alias":"STATE_NAME","length":25}],"features":[{"attributes":{"STATE_NAME":"Florida"},"geometry":{"rings":[[[-80.785662408630856,28.785194039580265], ... [-80.5878197219821,24.956376399079556],[-80.249453677873134,25.354937642313288]]]}}]}

(I have removed most of the geometry to make it easier reading)

8
  • how did you know to query layer 1, and that there was a field called STATE_NAME? That's what I'm trying to work out on-the-fly (ie, I need this to work for ANY rest endpoint at run-time, not one that I know beforehand). Thanks Aug 16, 2011 at 9:22
  • well the simplest answer would be to count the layers in the map service, and each other map service, and loop through them requesting the data. A query can just be a null one, so you bring everything back. You can then loop through the response listing the data.
    – Hairy
    Aug 16, 2011 at 9:41
  • so in my example above, I'd set a QueryTask based on each restEndPoint, and build a query which didn't return geometry - good idea. I'll give it a try - thanks! Aug 16, 2011 at 10:30
  • That's how I'd approach it
    – Hairy
    Aug 16, 2011 at 10:32
  • Try this: Url to layer URL/YOURLAYERNAME/MapServer/layers?f=json - This should return a json depiction of all your layers and their fields or URL/YOURLAYERNAME/MapServer/1?f=json indicating the layer number you want
    – Hairy
    Aug 16, 2011 at 10:45

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.