Select to view content in your preferred language

Datagrid and Map from JSON web service.

4911
5
Jump to solution
01-27-2015 08:38 AM
BrianPaulson1
Deactivated User

I was able to duplicate this example: Feature collection | ArcGIS API for JavaScript

using point data in a SQL Server Table (Web service which returns Json format data from SQL Server).

I wanted to take the Feature collection example a step further where I could add a interactive datagrid/map that is similar to this example: Add zoom button to DataGrid .

First, is a interactive datagrid/map possible from a Json feature collection?  All the examples I find require a feature layer that is on a spatial server.  If so, could someone please point me in the general direction to how this can be accomplished.  Sorry I am new to this and might have asked something really basic.  Any help would be greatly appreciated since I have spent a lot of time trying to figure this out.  Thanks

0 Kudos
1 Solution

Accepted Solutions
JakeSkinner
Esri Esteemed Contributor

Hi Brian,

It's possible to populate a datagrid with a feature collection (see below).  The one thing I am having trouble figuring out is how to zoom to the feature.

<!DOCTYPE html>
<html>  
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <!--The viewport meta tag is used to improve the presentation and behavior of the
    samples on iOS devices-->
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Flickr</title>
    <link rel="stylesheet" href="http://js.arcgis.com/3.12/dojo/resources/dojo.css">
    <link rel="stylesheet" href="http://js.arcgis.com/3.12/dijit/themes/claro/claro.css">
    <link rel="stylesheet" href="http://js.arcgis.com/3.12/dgrid/css/dgrid.css">
    <link rel="stylesheet" href="http://js.arcgis.com/3.12/esri/css/esri.css">

    <style>
      html, body, #map {
        height:100%;
        width:100%;
        margin:0;
        padding:0;
      }
      .esriScalebar{
        padding: 20px 20px; 
      } 
      #map{ 
        padding:0;
      }
      
      .dgrid { border: none; height: 100%; }
      .dgrid-column-0 {
        width: 35px;
      }
      .dgrid-row-odd {
        background: #FFFDF3;
      }
      td div img:hover {
        cursor: pointer;
      }

    </style>

    <script>var dojoConfig = { parseOnLoad: true };</script>
    <script src="http://js.arcgis.com/3.12/"></script>
    <script>
      var map, grid;
      require([
        "esri/map",
        "esri/layers/FeatureLayer",
        "esri/dijit/PopupTemplate",
        "esri/request",
        "esri/tasks/query",
        "esri/geometry/Point",
        "esri/graphic",
        "dojo/on",
        "dojo/_base/array",
        "dgrid/OnDemandGrid", "dgrid/Selection", "dojo/store/Memory",
        "dijit/form/Button", 
        "dojo/parser", "dojo/_base/declare",
        "dijit/layout/BorderContainer", "dijit/layout/ContentPane",
        "dojo/domReady!"
      ], function(
        Map, 
        FeatureLayer, 
        PopupTemplate,
        esriRequest,
        Query,
        Point,
        Graphic,
        on,        
        array,
        Grid, Selection, Memory,
        Button,
        parser, declare
      ) {
        
        parser.parse();
        
        var dataGrid = declare([Grid, Selection]);

        var columns = [{
          label: "",  //wasn't able to inject an HTML <div> with image here
          field: "ObjectID",
          formatter: makeZoomButton
        }, {
          label: "Title",
          field: "title"
        }];

        grid = new dataGrid({
          bufferRows: Infinity,
          columns: columns
        }, "grid");

        var featureLayer;

        map = new Map("map", {
          basemap: "satellite",
          center: [-46.807, 32.553],
          zoom: 3
        });

        //hide the popup if its outside the map's extent
        map.on("mouse-drag", function(evt) {
          if (map.infoWindow.isShowing) {
            var loc = map.infoWindow.getSelectedFeature().geometry;
            if (!map.extent.contains(loc)) {
              map.infoWindow.hide();
            }
          }
        });

        //create a feature collection for the flickr photos
        var featureCollection = {
          "layerDefinition": null,
          "featureSet": {
            "features": [],
            "geometryType": "esriGeometryPoint"
          }
        };
        featureCollection.layerDefinition = {
          "geometryType": "esriGeometryPoint",
          "objectIdField": "ObjectID",
          "drawingInfo": {
            "renderer": {
              "type": "simple",
              "symbol": {
                "type": "esriPMS",
                "url": "images/flickr.png",
                "contentType": "image/png",
                "width": 15,
                "height": 15
              }
            }
          },
          "fields": [{
            "name": "ObjectID",
            "alias": "ObjectID",
            "type": "esriFieldTypeOID"
          }, {
            "name": "title",
            "alias": "Title",
            "type": "esriFieldTypeString"
          }]
        };

        //define a popup template
        var popupTemplate = new PopupTemplate({
          title: "{title}",
          description: "{description}"
        });

        //create a feature layer based on the feature collection
        featureLayer = new FeatureLayer(featureCollection, {
          id: 'flickrLayer',
          infoTemplate: popupTemplate
        });

        //associate the features with the popup on click
        featureLayer.on("click", function(evt) {
          map.infoWindow.setFeatures([evt.graphic]);
        });
        

        map.on("layers-add-result", function(evt) {
          requestPhotos();                   
        });
        //add the feature layer that contains the flickr photos to the map
        map.addLayers([featureLayer]);

      function requestPhotos() {
        //get geotagged photos from flickr
        //tags=flower&tagmode=all
        var requestHandle = esriRequest({
          url: "http://api.flickr.com/services/feeds/geo?&format=json",
          callbackParamName: "jsoncallback"
        });
        requestHandle.then(requestSucceeded, requestFailed);
      }

      function requestSucceeded(response, io) {        
        //loop through the items and add to the feature layer
        var features = [];
        array.forEach(response.items, function(item) {
          var attr = {};
          attr["description"] = item.description;
          attr["title"] = item.title ? item.title : "Flickr Photo";

          var geometry = new Point(item);

          var graphic = new Graphic(geometry);
          graphic.setAttributes(attr);
          features.push(graphic);          
        });       
        
        var items = array.map(features, function(feature) {
              return feature.attributes;
            });

        var memStore = new Memory({
          data: items,
          idProperty: "ObjectID"
        });
        
        window.grid.set("store", memStore);
        window.grid.set("sort", "ObjectID");

        grid.on(".field-ObjectID:click", function(e) {
          //retrieve the ObjectId when someone clicks on the magnifying glass
          if (e.target.alt) {
            zoomRow(e.target.alt);
          }
        });


        featureLayer.applyEdits(features, null, null);
      }

      function requestFailed(error) {
        console.log('failed');
      }
      
      function makeZoomButton(id) {
          var zBtn = "<div data-dojo-type='dijit/form/Button'><img src='images/zoom.png' alt='" + id + "'";
          zBtn = zBtn + " width='18' height='18'></div>";
          return zBtn;
        }
        
      function zoomRow(id) {
        featureLayer.clearSelection();
        var query = new Query();
        query.objectIds = [id];
        featureLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW, function(features) {
          //zoom to the selected feature
          var newExtent = features[0].geometry.getExtent().expand(5.0);
          map.setExtent(newExtent);
        });
      }

    });
    </script>
  </head>
  <body class="claro">
    <div id="mainWindow" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'" style="width:100%; height:100%;">
      <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'" >
      </div>
      <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'left'" style="width:275px">
      <div id="grid"></div>
     </div>
    </div>
  </body>


</html>

View solution in original post

0 Kudos
5 Replies
JakeSkinner
Esri Esteemed Contributor

Hi Brian,

It's possible to populate a datagrid with a feature collection (see below).  The one thing I am having trouble figuring out is how to zoom to the feature.

<!DOCTYPE html>
<html>  
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <!--The viewport meta tag is used to improve the presentation and behavior of the
    samples on iOS devices-->
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Flickr</title>
    <link rel="stylesheet" href="http://js.arcgis.com/3.12/dojo/resources/dojo.css">
    <link rel="stylesheet" href="http://js.arcgis.com/3.12/dijit/themes/claro/claro.css">
    <link rel="stylesheet" href="http://js.arcgis.com/3.12/dgrid/css/dgrid.css">
    <link rel="stylesheet" href="http://js.arcgis.com/3.12/esri/css/esri.css">

    <style>
      html, body, #map {
        height:100%;
        width:100%;
        margin:0;
        padding:0;
      }
      .esriScalebar{
        padding: 20px 20px; 
      } 
      #map{ 
        padding:0;
      }
      
      .dgrid { border: none; height: 100%; }
      .dgrid-column-0 {
        width: 35px;
      }
      .dgrid-row-odd {
        background: #FFFDF3;
      }
      td div img:hover {
        cursor: pointer;
      }

    </style>

    <script>var dojoConfig = { parseOnLoad: true };</script>
    <script src="http://js.arcgis.com/3.12/"></script>
    <script>
      var map, grid;
      require([
        "esri/map",
        "esri/layers/FeatureLayer",
        "esri/dijit/PopupTemplate",
        "esri/request",
        "esri/tasks/query",
        "esri/geometry/Point",
        "esri/graphic",
        "dojo/on",
        "dojo/_base/array",
        "dgrid/OnDemandGrid", "dgrid/Selection", "dojo/store/Memory",
        "dijit/form/Button", 
        "dojo/parser", "dojo/_base/declare",
        "dijit/layout/BorderContainer", "dijit/layout/ContentPane",
        "dojo/domReady!"
      ], function(
        Map, 
        FeatureLayer, 
        PopupTemplate,
        esriRequest,
        Query,
        Point,
        Graphic,
        on,        
        array,
        Grid, Selection, Memory,
        Button,
        parser, declare
      ) {
        
        parser.parse();
        
        var dataGrid = declare([Grid, Selection]);

        var columns = [{
          label: "",  //wasn't able to inject an HTML <div> with image here
          field: "ObjectID",
          formatter: makeZoomButton
        }, {
          label: "Title",
          field: "title"
        }];

        grid = new dataGrid({
          bufferRows: Infinity,
          columns: columns
        }, "grid");

        var featureLayer;

        map = new Map("map", {
          basemap: "satellite",
          center: [-46.807, 32.553],
          zoom: 3
        });

        //hide the popup if its outside the map's extent
        map.on("mouse-drag", function(evt) {
          if (map.infoWindow.isShowing) {
            var loc = map.infoWindow.getSelectedFeature().geometry;
            if (!map.extent.contains(loc)) {
              map.infoWindow.hide();
            }
          }
        });

        //create a feature collection for the flickr photos
        var featureCollection = {
          "layerDefinition": null,
          "featureSet": {
            "features": [],
            "geometryType": "esriGeometryPoint"
          }
        };
        featureCollection.layerDefinition = {
          "geometryType": "esriGeometryPoint",
          "objectIdField": "ObjectID",
          "drawingInfo": {
            "renderer": {
              "type": "simple",
              "symbol": {
                "type": "esriPMS",
                "url": "images/flickr.png",
                "contentType": "image/png",
                "width": 15,
                "height": 15
              }
            }
          },
          "fields": [{
            "name": "ObjectID",
            "alias": "ObjectID",
            "type": "esriFieldTypeOID"
          }, {
            "name": "title",
            "alias": "Title",
            "type": "esriFieldTypeString"
          }]
        };

        //define a popup template
        var popupTemplate = new PopupTemplate({
          title: "{title}",
          description: "{description}"
        });

        //create a feature layer based on the feature collection
        featureLayer = new FeatureLayer(featureCollection, {
          id: 'flickrLayer',
          infoTemplate: popupTemplate
        });

        //associate the features with the popup on click
        featureLayer.on("click", function(evt) {
          map.infoWindow.setFeatures([evt.graphic]);
        });
        

        map.on("layers-add-result", function(evt) {
          requestPhotos();                   
        });
        //add the feature layer that contains the flickr photos to the map
        map.addLayers([featureLayer]);

      function requestPhotos() {
        //get geotagged photos from flickr
        //tags=flower&tagmode=all
        var requestHandle = esriRequest({
          url: "http://api.flickr.com/services/feeds/geo?&format=json",
          callbackParamName: "jsoncallback"
        });
        requestHandle.then(requestSucceeded, requestFailed);
      }

      function requestSucceeded(response, io) {        
        //loop through the items and add to the feature layer
        var features = [];
        array.forEach(response.items, function(item) {
          var attr = {};
          attr["description"] = item.description;
          attr["title"] = item.title ? item.title : "Flickr Photo";

          var geometry = new Point(item);

          var graphic = new Graphic(geometry);
          graphic.setAttributes(attr);
          features.push(graphic);          
        });       
        
        var items = array.map(features, function(feature) {
              return feature.attributes;
            });

        var memStore = new Memory({
          data: items,
          idProperty: "ObjectID"
        });
        
        window.grid.set("store", memStore);
        window.grid.set("sort", "ObjectID");

        grid.on(".field-ObjectID:click", function(e) {
          //retrieve the ObjectId when someone clicks on the magnifying glass
          if (e.target.alt) {
            zoomRow(e.target.alt);
          }
        });


        featureLayer.applyEdits(features, null, null);
      }

      function requestFailed(error) {
        console.log('failed');
      }
      
      function makeZoomButton(id) {
          var zBtn = "<div data-dojo-type='dijit/form/Button'><img src='images/zoom.png' alt='" + id + "'";
          zBtn = zBtn + " width='18' height='18'></div>";
          return zBtn;
        }
        
      function zoomRow(id) {
        featureLayer.clearSelection();
        var query = new Query();
        query.objectIds = [id];
        featureLayer.selectFeatures(query, FeatureLayer.SELECTION_NEW, function(features) {
          //zoom to the selected feature
          var newExtent = features[0].geometry.getExtent().expand(5.0);
          map.setExtent(newExtent);
        });
      }

    });
    </script>
  </head>
  <body class="claro">
    <div id="mainWindow" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design:'headline'" style="width:100%; height:100%;">
      <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'" >
      </div>
      <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'left'" style="width:275px">
      <div id="grid"></div>
     </div>
    </div>
  </body>


</html>
0 Kudos
BrianPaulson1
Deactivated User

Jake,

Thank you so much for answering with the code.  You have made my day.  I am looking at this example:Zoom to Point using Show Find Task results in DataGrid Sample to try and figure out how to zoom to the feature(point) from the datagrid.  I am guessing I have to figure out the extent of the points.

0 Kudos
KellyHutchins
Esri Frequent Contributor

You could use centerAndZoom to zoom to the point. Here's an example based on Jake's code that shows this:

Flickr

Or you could use code like the example in this post   that will create an extent based on the point:

Zoom to Point using Show Find Task results in DataGrid Sample

BrianPaulson1
Deactivated User

Kelly,

Thank you.  You and Jake have been very helpful.  I now am displaying my data exactly as I wished.

0 Kudos
MahtabAlam1
Frequent Contributor

Jake,

You need to assign the Ids in requestSucceeded function something like :

var oid = 0;

        array.forEach(response.items, function(item) { 

          var attr = {};

   oid = oid + 1;

          attr["description"] = item.description; 

          attr["title"] = item.title ? item.title : "Flickr Photo"; 

  attr["ObjectID"] = oid;

 

          var geometry = new Point(item); 

 

          var graphic = new Graphic(geometry); 

          graphic.setAttributes(attr); 

          features.push(graphic);           

        });

Other then that, please look at Kelly's reply for zoom to point feature.

0 Kudos