Select Record in Datagrid and Zoom to Point

3926
10
08-16-2013 09:59 PM
WillHughes1
Occasional Contributor II
I modified one of the samples which uses the FindTask and displays the results in a Datagrid. When the Datagrid is click the map zooms to the extent of the selected feature.
I changed the map service from a Tax Parcel (polygon) service to the Cities (point) service.
Everything works except for the zoom to on selecting a record in the Datagrid. I assume the issue has to do with the geometry type.
<!DOCTYPE html><html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=7, IE=9, IE=10">
    <!--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>Display Find Task results in Dojo DataGrid</title>


    <link rel="stylesheet" href="http://js.arcgis.com/3.6/js/dojo/dijit/themes/claro/claro.css">
    <link rel="stylesheet" href="http://js.arcgis.com/3.6/js/dojo/dojox/grid/resources/Grid.css">
    <link rel="stylesheet" href="http://js.arcgis.com/3.6/js/dojo/dojox/grid/resources/claroGrid.css">
    <link rel="stylesheet" href="http://js.arcgis.com/3.6/js/esri/css/esri.css">
    <style>
      html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
    </style>


    <script>var dojoConfig = { parseOnLoad:true }</script>
    <script src="http://js.arcgis.com/3.6/"></script>
    <script>
      dojo.require("esri.map");
      dojo.require("dojox.grid.DataGrid");
      dojo.require("dojo.data.ItemFileReadStore");
      dojo.require("esri.tasks.find");
      dojo.require("dijit.layout.BorderContainer");
      dojo.require("dijit.layout.ContentPane");
      dojo.require("dijit.form.Button");
      
      var findTask, findParams;
      var map, center, zoom;
      var grid, store;


      function init() {
        dojo.connect(grid, "onRowClick", onRowClickHandler);


        center = [-83.266, 42.568];
        zoom = 4;
        map = new esri.Map("map", { 
          basemap: "streets",
          center: center,
          zoom: zoom
        });


        //Create Find Task using the URL of the map service to search
        findTask = new esri.tasks.FindTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/");


        dojo.connect(map, "onLoad", function() {
          //Create the find parameters
          findParams = new esri.tasks.FindParameters();
          findParams.returnGeometry = true;
          findParams.layerIds = [0];
          findParams.searchFields = ["CITY_NAME","STATE_NAME","POP1990"];
          findParams.outSpatialReference = map.spatialReference;
          console.log("find sr: ", findParams.outSpatialReference);
        });
      }


      function doFind() {
        //Set the search text to the value in the box
        findParams.searchText = dojo.byId("ownerName").value;
        findTask.execute(findParams,showResults);
      }


      function showResults(results) {
        //This function works with an array of FindResult that the task returns
        map.graphics.clear();
        var symbol = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE, 10, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([255, 0, 0]), 1), new dojo.Color([0, 255, 0, 0.25]));


        //create array of attributes
        var items = dojo.map(results,function(result){
          var graphic = result.feature;
          graphic.setSymbol(symbol);
          map.graphics.add(graphic);
          return result.feature.attributes;
        });
        
        //Create data object to be used in store
        var data = {
          identifier: "FID",  //This field needs to have unique values
          label: "FID", //Name field for display. Not pertinent to a grid but may be used elsewhere.
          items: items
        };


         //Create data store and bind to grid.
        store = new dojo.data.ItemFileReadStore({ data:data });
        var grid = dijit.byId('grid');
        grid.setStore(store);


        //Zoom back to the initial map extent
        map.centerAndZoom(center, zoom);
      }


      //Zoom to the parcel when the user clicks a row
      function onRowClickHandler(evt){
        var clickedTaxLotId = grid.getItem(evt.rowIndex).FID;
        var selectedTaxLot;


        dojo.forEach(map.graphics.graphics,function(graphic){
          if((graphic.attributes) && graphic.attributes.FID === clickedTaxLotId){
            selectedTaxLot = graphic;
            return;
          }
        });
        var taxLotExtent = selectedTaxLot.geometry.getExtent();
        map.setExtent(taxLotExtent);
      }


      dojo.ready(init);
    </script>
  </head>
  <body class="claro">
  <div data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design:'headline'"  style="width:100%;height:100%;margin:0;">
    <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'top'" style="height:40px;">
      Owner name: <input type="text" id="ownerName" size="60" value="Raleigh" />
      <button data-dojo-type="dijit.form.Button"  data-dojo-props='onClick:function(){ doFind();}, value:"Search"'>
        Search
      </button>
    </div>
    <div id="map" data-dojo-props="region:'center'" data-dojo-type="dijit.layout.ContentPane" style="border:1px solid #000;"></div>
    <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'bottom'" style="height:150px;">
     <table data-dojo-type="dojox.grid.DataGrid" data-dojo-id="grid"  id="grid" data-dojo-props="rowsPerPage:'5', rowSelector:'20px'">
      <thead>
        <tr>
        <th field="FID">FID</th>
          <th field="CITY_NAME">City</th>
          <th field="STATE_NAME" >State</th>
          <th field="POP1990">Population</th>
        </tr>
      </thead>
    </table>
    </div>
  </div>
  </body>
</html>


10 Replies
JasonZou
Occasional Contributor III
You guess right. Point extent is still a point. You can recenter the map to the selected point, but not zoom it to a point. Two options:
1. Create an extent around the point:
var distance = 500;
var newExtent = new esri.geometry.Extent({
    "xmin": pnt.x - distance,
    "ymin": pnt.y - distance,
    "xmax": pnt.x + distance,
    "ymax": pnt.y + distance,
    "spatialReference":{"wkid":4326}    // change 4326 to your choice
});
map.setExtent(newExtent);
2. As you already coded, use map.centerAndZoom(center, zoom);
3. Use geometryService to create a buffer around the point, and zoom the map to the result extent in the callback function.
0 Kudos
KennethRichards
New Contributor III
You guess right. Point extent is still a point. You can recenter the map to the selected point, but not zoom it to a point. Two options:
1. Create an extent around the point:
var distance = 500;
var newExtent = new esri.geometry.Extent({
    "xmin": pnt.x - distance,
    "ymin": pnt.y - distance,
    "xmax": pnt.x + distance,
    "ymax": pnt.y + distance,
    "spatialReference":{"wkid":4326}    // change 4326 to your choice
});
map.setExtent(newExtent);
2. As you already coded, use map.centerAndZoom(center, zoom);
3. Use geometryService to create a buffer around the point, and zoom the map to the result extent in the callback function.


How would you pass the coordinants of the point to pnt.x?
Here is my function so far.

function makeZoomButton(id){//id is objectid
        var zBtn = "<div data-dojo-type='dijit.form.Button'><img src='photos/bg_magnify.png'";
        zBtn = zBtn + " width='18' height='18'";
        zBtn = zBtn + " onClick=\"zoomRow('"+id+"')\"></div>"; //activates zoomRow function
        return zBtn;
      }

    function zoomRow(id){
        var grid = dijit.byId('grid');
        var clickedWell = grid.getItem(id);
        var selectedWell;
        var distance = 500;
        var newExtent = new esri.geometry.Extent({
            "xmin": pt.x - distance,
            "ymin": pt.y - distance,
            "xmax": pt.x + distance,
            "ymax": pt.y + distance,
            "spatialReference":{"wkid":4326}
        });

        console.log(map.graphics.graphics);
}
0 Kudos
JasonZou
Occasional Contributor III
function zoomRow(id) {
    var grid = dijit.byId('grid');
    var clickedWell = grid.getItem(id);
    var selectedWell;
    var distance = 500;
    
    dojo.forEach(map.graphics.graphics, function (graphic) {
        if ((graphic.attributes) && graphic.attributes.FID === clickedWell.FID) {
            selectedWell = graphic.geometry;
            return;
        }
    });
    
    var newExtent = new esri.geometry.Extent({
        "xmin": selectedWell.x - distance,
        "ymin": selectedWell.y - distance,
        "xmax": selectedWell.x + distance,
        "ymax": selectedWell.y + distance,
        "spatialReference": {
            "wkid": 4326
        }
    });
    map.setExtent(taxLotExtent);
    console.log(map.graphics.graphics);
}
0 Kudos
KennethRichards
New Contributor III
function zoomRow(id) {
    var grid = dijit.byId('grid');
    var clickedWell = grid.getItem(id);
    var selectedWell;
    var distance = 500;
    
    dojo.forEach(map.graphics.graphics, function (graphic) {
        if ((graphic.attributes) && graphic.attributes.FID === clickedWell.FID) {
            selectedWell = graphic.geometry;
            return;
        }
    });
    
    var newExtent = new esri.geometry.Extent({
        "xmin": selectedWell.x - distance,
        "ymin": selectedWell.y - distance,
        "xmax": selectedWell.x + distance,
        "ymax": selectedWell.y + distance,
        "spatialReference": {
            "wkid": 4326
        }
    });
    map.setExtent(taxLotExtent);
    console.log(map.graphics.graphics);
}


Thanks for the help.

Now it's not liking selectedWell.x ,
I know its because I never set selectedWell to anything. Any idea on how to do that?
0 Kudos
JasonZou
Occasional Contributor III
In my previous post, I assume all the map.graphics.graphics are points and clickedWell contains the feature attributes. If my assumption is not your case, you will need to modify it accordingly. What I would recommend is to create a graphics layer for each specific purpose instead of using the general map.graphics, so you have control on what graphics type you will add to each graphics layer.

Specific to your question, what is the value of selectedWell after the forEach loop? If undefined, then no matching graphic found.
0 Kudos
KennethRichards
New Contributor III
In my previous post, I assume all the map.graphics.graphics are points and clickedWell contains the feature attributes. If my assumption is not your case, you will need to modify it accordingly. What I would recommend is to create a graphics layer for each specific purpose instead of using the general map.graphics, so you have control on what graphics type you will add to each graphics layer.

Specific to your question, what is the value of selectedWell after the forEach loop? If undefined, then no matching graphic found.


Your assumption was correct. I just set it equal to map.graphics.graphics after my last post and that seemed to solve that problem. Now my extent gets screwed up when it attempts to zoom. It looks like it is losing the coordinate system. All the layers that only appear at certain extents try to draw at the same time and my map goes blank. Any ideas on that one?

[ATTACH=CONFIG]27118[/ATTACH]
0 Kudos
JasonZou
Occasional Contributor III
You are using ESRI basemap, right? If so, all esri map services use web mercator spatial reference.

Change:
var newExtent = new esri.geometry.Extent({
        "xmin": selectedWell.x - distance,
        "ymin": selectedWell.y - distance,
        "xmax": selectedWell.x + distance,
        "ymax": selectedWell.y + distance,
        "spatialReference": {
            "wkid": 4326
        }
    });


To:
var newExtent = new esri.geometry.Extent({
        "xmin": selectedWell.x - distance,
        "ymin": selectedWell.y - distance,
        "xmax": selectedWell.x + distance,
        "ymax": selectedWell.y + distance,
        "spatialReference": {
            "wkid": 102100
        }
    });
0 Kudos
LawrenceRover
New Contributor III
Has anyone had any luck converting this to zoom to points?  Any help would be greatly appreciated.

//Zoom to the parcel when the user clicks a row
        function onRowClickHandler(evt) {
          var clickedTaxLotId = evt.grid.getItem(evt.rowIndex).PARCELID;
          var selectedTaxLot = arrayUtils.filter(map.graphics.graphics, function (graphic) {
            return ((graphic.attributes) && graphic.attributes.PARCELID === clickedTaxLotId);
          });
          if ( selectedTaxLot.length ) {
            map.setExtent(selectedTaxLot[0].geometry.getExtent(), true);
          }
        }
      });      


Thanks,

Larry Rover
GIS Manager
RA Consultants
0 Kudos
CesarDuran
New Contributor II
Using map.centerAndZoom is a good approach too. I am not sure if that is what you want.


function onRowClickHandler(evt) {
                var clickedTaxLotId = evt.grid.getItem(evt.rowIndex).MyID;                
                var selectedTaxLot = arrayUtils.filter(map.graphics.graphics, function (graphic) {
                    return ((graphic.attributes) && graphic.attributes.MyID === clickedTaxLotId);
                });
                //CREATE THE POINT WITH THE SELECTED ROW
                var center2 = [selectedTaxLot[0].geometry.getLongitude(), selectedTaxLot[0].geometry.getLatitude()];
                //ZOOM LEVEL
                var zoom2 = 15;
                //CENTER AND ZOOM
                map.centerAndZoom(center2, zoom2);
            }