Select related features look up datagrid.

5272
10
Jump to solution
02-11-2015 02:14 PM
RickeyFight
MVP Regular Contributor

So what I want to do, is to be able to select a line feature (trails) and have related lines, based on attributes, selected too.

What I am thinking is in a data grid.  I have been playing with ways to do this.

I have tried Query related records | ArcGIS API for JavaScript

I have tried Datagrid look up. Neither way seems to work the way I am wanting.

Ultimately I want to join this with the Elevations Profile web-app. I can do this part (I hope), if I can figure how to select related features.

Our data has multiple trails that split off of each other.

0 Kudos
1 Solution

Accepted Solutions
KellyHutchins
Esri Frequent Contributor

Rickey,

Here's some sample code that shows how to display related records. In this example click on a point then use the 'Show Related Records' link to display a table showing related record info.

If your resulting app (based on the Elevation template) is going to be public I'd love to see what you come up with.

<!DOCTYPE html>
  <html>
  <head>
  <title>Display Related Records</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
  <link rel="stylesheet" href="https://community.esri.com//jsdev.arcgis.com/3.13/dgrid/css/dgrid.css">
  <link rel="stylesheet" href="https://community.esri.com//jsdev.arcgis.com/3.13/dgrid/css/skins/claro.css">
  <link rel="stylesheet" href="http://js.arcgis.com/3.12/esri/css/esri.css">
  <style>
    html,body,#mapDiv,.map.container{
      padding:0;
      margin:0;
      height:100%;
    }
    #tableContainer{
      position: absolute;
      z-index: 99;
      bottom:0;
      right:0;
      left:0;
      height: 15%;
    }
  </style>


  <script>var dojoConfig = { parseOnLoad: true };</script>
  <script src="http://js.arcgis.com/3.12"></script>
  <script>
    var map,grid = null,
        webmapId = "283117cc8d5c4028acc30a0609d58254";


        //Note the web map id has related records 
    
    require([
      "esri/map",
      "esri/arcgis/utils",
      "dgrid/OnDemandGrid",
      "dojo/store/Memory",
      "esri/tasks/RelationshipQuery",
      "esri/domUtils",
      "dojo/dom-construct",
      "dojo/query",
      "dojo/_base/array",
      "dojo/_base/window",
      "dijit/registry",
      "dojo/on",
      "dojo/domReady!"
      ], function (Map, arcgisUtils, Grid, Memory, RelationshipQuery, domUtils, domConstruct, query, array, win, registry, on) {
        arcgisUtils.createMap(webmapId, "mapDiv").then(function (response) {
        map = response.map;
        on(map.infoWindow, "hide", function(){
          //close the table if open 
          clearGrid();
        });
        //add a link to the popup that for getting related records 
        var link = domConstruct.create("a",{
          "class": "action", 
          "id": "relatedLink",
          "innerHTML": "Show Related Records", //text that appears in the popup for the link 
          "href": "javascript: void(0);"
        }, query(".actionList", window.map.infoWindow.domNode)[0]);




        on(link, "click", function(){
          //Get info from the selected feature 
          var feature = map.infoWindow.getSelectedFeature();
          var layer = feature.getLayer();
          var OIDField = layer.objectIdField;
          var oids = feature.attributes[OIDField];


          //Setup the relationship query 
          var relatedQuery = new RelationshipQuery();
          relatedQuery.outFields = ["*"];
          relatedQuery.relationshipId = 0;
          relatedQuery.objectIds = [oids];


          //Perform the query
          layer.queryRelatedFeatures(relatedQuery, function(relatedRecords){
            //get the related records for the input OID. In this case there
            //is just one object id. 
            clearGrid();
            var featureSet = relatedRecords[oids];
            if(featureSet && featureSet.features){
             createTable(featureSet);
            }else{
              console.log("No related records");
            }




          });


        });
    });


      function clearGrid(){
        //clear existing grid 
        if(grid){
            grid.set("store",new Memory({data:[]}));
            domUtils.hide(grid.domNode);
        }
      }
      function createTable(featureSet, info){
        var data = [];      
        array.forEach(featureSet.features, function(r){
          data.push(r.attributes);
        });
        //define the columns
        var relatedLayer = featureSet.features[0].getLayer();
        var columns = {};
        array.forEach(relatedLayer.fields, function(f){
          columns[f.name] = f.alias;
        });
        var memoryStore =  new Memory({data: data});


        grid = new Grid({
          columns: columns
        },"tableContainer");




        grid.set("store", memoryStore);
        domUtils.show(grid.domNode);










      }
    });
  </script>


  </head>


  <body class="claro">
    <div id="mapDiv"></div>
    <div id="tableContainer"></div>
  </body>
  </html>

View solution in original post

10 Replies
KellyHutchins
Esri Frequent Contributor

Rickey,

Here's some sample code that shows how to display related records. In this example click on a point then use the 'Show Related Records' link to display a table showing related record info.

If your resulting app (based on the Elevation template) is going to be public I'd love to see what you come up with.

<!DOCTYPE html>
  <html>
  <head>
  <title>Display Related Records</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
  <link rel="stylesheet" href="https://community.esri.com//jsdev.arcgis.com/3.13/dgrid/css/dgrid.css">
  <link rel="stylesheet" href="https://community.esri.com//jsdev.arcgis.com/3.13/dgrid/css/skins/claro.css">
  <link rel="stylesheet" href="http://js.arcgis.com/3.12/esri/css/esri.css">
  <style>
    html,body,#mapDiv,.map.container{
      padding:0;
      margin:0;
      height:100%;
    }
    #tableContainer{
      position: absolute;
      z-index: 99;
      bottom:0;
      right:0;
      left:0;
      height: 15%;
    }
  </style>


  <script>var dojoConfig = { parseOnLoad: true };</script>
  <script src="http://js.arcgis.com/3.12"></script>
  <script>
    var map,grid = null,
        webmapId = "283117cc8d5c4028acc30a0609d58254";


        //Note the web map id has related records 
    
    require([
      "esri/map",
      "esri/arcgis/utils",
      "dgrid/OnDemandGrid",
      "dojo/store/Memory",
      "esri/tasks/RelationshipQuery",
      "esri/domUtils",
      "dojo/dom-construct",
      "dojo/query",
      "dojo/_base/array",
      "dojo/_base/window",
      "dijit/registry",
      "dojo/on",
      "dojo/domReady!"
      ], function (Map, arcgisUtils, Grid, Memory, RelationshipQuery, domUtils, domConstruct, query, array, win, registry, on) {
        arcgisUtils.createMap(webmapId, "mapDiv").then(function (response) {
        map = response.map;
        on(map.infoWindow, "hide", function(){
          //close the table if open 
          clearGrid();
        });
        //add a link to the popup that for getting related records 
        var link = domConstruct.create("a",{
          "class": "action", 
          "id": "relatedLink",
          "innerHTML": "Show Related Records", //text that appears in the popup for the link 
          "href": "javascript: void(0);"
        }, query(".actionList", window.map.infoWindow.domNode)[0]);




        on(link, "click", function(){
          //Get info from the selected feature 
          var feature = map.infoWindow.getSelectedFeature();
          var layer = feature.getLayer();
          var OIDField = layer.objectIdField;
          var oids = feature.attributes[OIDField];


          //Setup the relationship query 
          var relatedQuery = new RelationshipQuery();
          relatedQuery.outFields = ["*"];
          relatedQuery.relationshipId = 0;
          relatedQuery.objectIds = [oids];


          //Perform the query
          layer.queryRelatedFeatures(relatedQuery, function(relatedRecords){
            //get the related records for the input OID. In this case there
            //is just one object id. 
            clearGrid();
            var featureSet = relatedRecords[oids];
            if(featureSet && featureSet.features){
             createTable(featureSet);
            }else{
              console.log("No related records");
            }




          });


        });
    });


      function clearGrid(){
        //clear existing grid 
        if(grid){
            grid.set("store",new Memory({data:[]}));
            domUtils.hide(grid.domNode);
        }
      }
      function createTable(featureSet, info){
        var data = [];      
        array.forEach(featureSet.features, function(r){
          data.push(r.attributes);
        });
        //define the columns
        var relatedLayer = featureSet.features[0].getLayer();
        var columns = {};
        array.forEach(relatedLayer.fields, function(f){
          columns[f.name] = f.alias;
        });
        var memoryStore =  new Memory({data: data});


        grid = new Grid({
          columns: columns
        },"tableContainer");




        grid.set("store", memoryStore);
        domUtils.show(grid.domNode);










      }
    });
  </script>


  </head>


  <body class="claro">
    <div id="mapDiv"></div>
    <div id="tableContainer"></div>
  </body>
  </html>
RickeyFight
MVP Regular Contributor

Thank you! That helped a lot!

I was wondering if there was a way to zoom to a record in the table? Or is the table the related table and one cannot zoom?

How can I remove some fields so they do not display in the table?

On another note, is it possible to have the relate table relate off of 3 different fields?

0 Kudos
KellyHutchins
Esri Frequent Contributor

Yes you can zoom  if the related data is a layer. In the example above its just tabular data so there is no feature geometry. To zoom you'll just get the geometry of the feature and set the map extent.  There are several threads with more info on zooming to features and a good blog post here with more details.

You can remove fields by setting the outFields for the relatedQuery to include just the fields you are interested in so here we just get back info from two fields:

         relatedQuery.outFields = ["YAPIID", "OPERATIONNUMBER"];

Then you'll want to update the code that generates the table columns to just display those two fields:

        var columns = {

          "YAPIID": "ID",

          "OPERATIONNUMBER": "Op Number"

        }

As far as having the relate table relate off of three different fields I'm not sure. Since the relationship is set up in ArcGIS Server you may want to post your question about creating the relationship to the ArcGIS Server place.

RickeyFight
MVP Regular Contributor

I replaced the relatedQuery and var columns like you suggested. The relatedQuery part worked but the table now shows every row and only populates the two fields. layerlist.PNG

0 Kudos
KellyHutchins
Esri Frequent Contributor

Looks like the columns may not be specified correctly? Can you post that portion of your code?

0 Kudos
RickeyFight
MVP Regular Contributor

I copied your suggestions into the code you provided above and it did not work.

//Setup the relationship query 

          var relatedQuery = new RelationshipQuery();

          relatedQuery.outFields = ["ROUTE_1 ","ROUTE_2 ","NAME ","GROUP_","LENGTH"];

          relatedQuery.relationshipId = 0;

          relatedQuery.objectIds = [oids];

And

  //define the columns

        var relatedLayer = featureSet.features[0].getLayer();

        var columns = {

   "ROUTE_1": "Route 1",

    "ROUTE_2": "Route 2 ",

   "NAME ": "Name",

   "GROUP_": "Group",

   "LENGTH ": "Length (ft)"

  };

        array.forEach(relatedLayer.fields, function(f){

          columns[f.name] = f.alias;

        });

0 Kudos
KellyHutchins
Esri Frequent Contributor

You need to remove this portion of code that creates a new column for each field in the layer.

        array.forEach(relatedLayer.fields, function(f){

          columns[f.name] = f.alias;

        });

RickeyFight
MVP Regular Contributor

That was it,

Thank you!

My project is not done yet but you can go to the elevation link in my question to see my progress.

(if it is not working it is because I am still in development and I am changing the script)

RickeyFight
MVP Regular Contributor

I did find an issue with the related records code. For some reason the first time the map loads, the area where the related records table shows does not act properly. When I try to move the map, it highlights the map and will not let it move.

In the example you provided the bottom 15% (the side of the table) of the map cannot be navigated like normal.

Is there a way to change the z value or change the height to 0 until the table is displayed?

I also changed my services so that the related layer is a line layer. When I select the table it does not move to selected location.

"Yes you can zoom  if the related data is a layer. In the example above its just tabular data so there is no feature geometry. To zoom you'll just get the geometry of the feature and set the map extent."

Any suggestions?

Thank you

0 Kudos