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
Solved! Go to Solution.
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>
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>
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.
You could use centerAndZoom to zoom to the point. Here's an example based on Jake's code that shows this:
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
Kelly,
Thank you. You and Jake have been very helpful. I now am displaying my data exactly as I wished.
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.