Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I'm creating a simple ArcGIS application that shows a table of data from a feature layer, one of which is a URL string. I'd like to make that string be a clickable hyperlink. Is this possible and if so what am I doing wrong. Below is my code. As you can see in the "UpdateGrid" function I'm creating a tag and inserting it into the cell. This is rendering fine and showing the URL but it's not clickable.

<!DOCTYPE html>
  <html>
  <head>
  <title>Stream Gauge Monitors</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="http://js.arcgis.com/3.7/js/dojo/dijit/themes/tundra/tundra.css">
  <link rel="stylesheet" type="text/css" href="http://js.arcgis.com/3.7/js/esri/css/esri.css">

  <style>
    html,body,#mapDiv,.map.container{
      padding:0;
      margin:0px;
      height:100%;
    }

    #legendDiv{
      background-color: #fff;
      position: absolute !important;
      z-index: 99;
      top:10px;
      right:20px;
      border-radius:20px;
    }

   body {
      overflow: hidden;
      overflow: hidden;
      font-family: "Roboto Condensed", sans-serif;
      font-size: 0.90em;
      margin: 0 auto;
      width: 100%;
    }

    #grid {
      height: 80%;
      width: 100%;
    }

    .field-NAME {
      width: 5%;
      font-size: .80em;
      font-weight: normal;
    }

    .field-CURRENT_STAGE {
      width: 2%;
      font-size: .80em;
      font-weight: normal;
    }

    .field-ALERT_STATUS {
      width: 2%;
      font-size: .80em;
      font-weight: normal;
    }

    .field-LINK {
      width: 5%;
      font-size: .80em;
      font-weight: normal;
    }

    #grid .dgrid-row-odd {
      background: #F2F5F9;
    }

    .dgrid-no-data, .dgrid-loading {
      color: #aaa;
      font-size: 3em;
      padding: 3em;
      text-align: center;
    }
  </style>

  <script>var dojoConfig = { parseOnLoad: true };</script>
  <script src="http://js.arcgis.com/3.7compact/"></script>
  <script>
      var map,
          webmapId = "a8ca5a7d13b6458997352d82700e07c6",
          featureLayer, pageInfo, grid;

      require([
        "esri/map",
        "esri/arcgis/utils",
        "esri/dijit/Legend",
        "esri/layers/FeatureLayer",
        "esri/tasks/query",
        "esri/TimeExtent",
        "dojo/number",
        "dojo/date/locale",
        "dojo/dom",
        "dojo/on",
        "dojo/_base/array",
        "dojo/store/Memory",
        "dgrid/OnDemandGrid",
        "dojo/domReady!"
      ], function (Map, arcgisUtils, Legend, FeatureLayer, Query, TimeExtent,
        number, locale, dom, on,
        arrayUtils, Memory,
        OnDemandGrid) {
          arcgisUtils.createMap(webmapId, "mapDiv").then(function (response) {
              map = response.map

              var legend = new Legend({
                  map: map,
                  layerInfos: (arcgisUtils.getLegendLayers(response))
              }, "legendDiv");

              legend.startup();
          });

          var sortAttr = [{
              attribute: "name",
              descending: true
          }];
          grid = new OnDemandGrid({
              store: Memory({
                  idProperty: "OBJECTID"
              }),
              columns: {
                  NAME: "NAME",
                  CURRENT_STAGE: "CURRENT STAGE",
                  ALERT_STATUS: "ALERT STATUS",
                  LINK: "Link to Flood Data Image",
              },
              loadingMessage: "Loading data...",
              noDataMessage: "No results found.",
              sort: sortAttr
          }, "grid");

          // create a feature layer
          featureLayer = new FeatureLayer("http://geoweb.cityofsalem.net/salemgis/rest/services/Public/IT_StreamMonitoringStations/MapServer/0", {
              outFields: ["*"]
          });

          // get object IDs from the table (feature layer)
          featureLayer.on("load", function () {
              // create the query to fetch object IDs for earthquakes that have a magnitude greater than 6.0
              // that occurred after January 1st 2007
              var query = new Query();
              query.where = "OBJECTID > 0";
              featureLayer.queryIds(query, function (objectIds) {
                  fetchRecords(objectIds);
              });
          });

          // click listeners for prev/next page buttons
          on(dom.byId("prev"), "click", function () {
              queryRecordsByPage(pageInfo.currentPage - 1);
          });
          on(dom.byId("next"), "click", function () {
              queryRecordsByPage(pageInfo.currentPage + 1);
          });

          // formatting function for numbers
          function formatRound(value) {
              return number.round(value, 2);
          }

          // formatting function for dates
          function formatDate(value) {
              var inputDate = new Date(value);
              return locale.format(inputDate, {
                  selector: "date",
                  datePattern: "MMMM d, y"
              });
          }

          function fetchRecords(objectIds) {
              if (objectIds.length > 0) {
                  updatePageInformation(objectIds);
                  queryRecordsByPage(1);
              } else {
                  grid.showMessage("No matching records");
                  grid.setStore(null);
              }
          }

          function updatePageInformation(objectIds, page) {
              pageInfo = {
                  objectIds: objectIds,
                  totalRecords: objectIds.length,
                  totalPages: Math.ceil(objectIds.length / 15),
                  currentPage: page || 0,
                  recordsPerPage: 15
              };

              dom.byId("pageInfo").innerHTML = pageInfo.currentPage + "/" + pageInfo.totalPages;
              dom.byId("recordsInfo").innerHTML = pageInfo.totalRecords;

              if (pageInfo.currentPage > pageInfo.totalPages) {
                  queryRecordsByPage(pageInfo.currentPage - 1);
              }
          }

          function queryRecordsByPage(pageNumber) {
              // check if the page number is valid
              if (pageNumber < 1 || pageNumber > pageInfo.totalPages) {
                  return;
              }

              //grid.showMessage("Fetching records...");

              var begin = pageInfo.recordsPerPage * (pageNumber - 1);
              var end = begin + pageInfo.recordsPerPage;

              // create the query
              var query = new Query();
              query.objectIds = pageInfo.objectIds.slice(begin, end);
              query.outFields = ["*"];

              // Query for the records with the given object IDs and populate the grid
              featureLayer.queryFeatures(query, function (featureSet) {
                  updateGrid(featureSet, pageNumber);
              });
          }

          function updateGrid(featureSet, pageNumber) {

              var data = arrayUtils.map(featureSet.features, function (entry, i) {

                  var a = document.createElement('a');
                  var linkText = document.createTextNode(entry.attributes.LINK);
                  a.appendChild(linkText);
                  a.title =  entry.attributes.LINK;
                  a.href = entry.attributes.LINK;

                  return {
                      NAME: entry.attributes.NAME,
                      CURRENT_STAGE: entry.attributes.CURRENT_STAGE,
                      ALERT_STATUS: entry.attributes.ALERT_STATUS,
                      LINK: a
                  };
              });
              grid.store.setData(data);
              grid.refresh();

              // update application state
              pageInfo.currentPage = pageNumber;
              dom.byId("pageInfo").innerHTML = pageInfo.currentPage + "/" + pageInfo.totalPages;
          }

      });
  </script>

  </head>

  <body>
    <div id="mapDiv" style="height: 55%"></div>
    <div id="tbl" style="height:45%">

      <p>
  Total records: 
  <span id="recordsInfo">0</span>
  &nbsp;&nbsp;|&nbsp;&nbsp;

  <button id="prev">Prev Page</button>
  &nbsp;&nbsp<span id="pageInfo"></span>&nbsp;&nbsp

  <button id="next">Next Page</button>
</p>

<!-- dgrid will be created in this div -->
<div id="grid"></div>
    </div>
    <div id="legendDiv"></div>
  </body>
  </html>
share|improve this question

1 Answer 1

up vote 1 down vote accepted

When defining the columns for your grid, you can specify a formatting function to transform the value from the data store to something else. To do this, you need to modify your column definition and also define the function that will turn your URL into a link. Here's the relevant code:

grid = new OnDemandGrid({
    store: Memory({
        idProperty: "OBJECTID"
    }),
    columns: {
        NAME: "NAME",
        CURRENT_STAGE: "CURRENT STAGE",
        ALERT_STATUS: "ALERT STATUS",
        LINK: { label: "Link to Flood Data Image", formatter: makeLink }
    },
    loadingMessage: "Loading data...",
    noDataMessage: "No results found.",
    sort: sortAttr
}, "grid");

And the makeLink function:

function makeLink(data) {
  console.log("make link", data);
  return "<a target=\"_blank\" href=\"" + data + "\">" + data + "</a>";
}

Here's a full working version:

<!DOCTYPE html>
  <html>
  <head>
  <title>Stream Gauge Monitors</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="http://js.arcgis.com/3.7/js/dojo/dijit/themes/tundra/tundra.css">
  <link rel="stylesheet" type="text/css" href="http://js.arcgis.com/3.7/js/esri/css/esri.css">

  <style>
    html,body,#mapDiv,.map.container{
      padding:0;
      margin:0px;
      height:100%;
    }

    #legendDiv{
      background-color: #fff;
      position: absolute !important;
      z-index: 99;
      top:10px;
      right:20px;
      border-radius:20px;
    }

   body {
      overflow: hidden;
      overflow: hidden;
      font-family: "Roboto Condensed", sans-serif;
      font-size: 0.90em;
      margin: 0 auto;
      width: 100%;
    }

    #grid {
      height: 80%;
      width: 100%;
    }

    .field-NAME {
      width: 5%;
      font-size: .80em;
      font-weight: normal;
    }

    .field-CURRENT_STAGE {
      width: 2%;
      font-size: .80em;
      font-weight: normal;
    }

    .field-ALERT_STATUS {
      width: 2%;
      font-size: .80em;
      font-weight: normal;
    }

    .field-LINK {
      width: 5%;
      font-size: .80em;
      font-weight: normal;
    }

    #grid .dgrid-row-odd {
      background: #F2F5F9;
    }

    .dgrid-no-data, .dgrid-loading {
      color: #aaa;
      font-size: 3em;
      padding: 3em;
      text-align: center;
    }
  </style>

  <script>var dojoConfig = { parseOnLoad: true };</script>
  <script src="http://js.arcgis.com/3.7compact/"></script>
  <script>
      var map,
          webmapId = "a8ca5a7d13b6458997352d82700e07c6",
          featureLayer, pageInfo, grid;

      require([
        "esri/map",
        "esri/arcgis/utils",
        "esri/dijit/Legend",
        "esri/layers/FeatureLayer",
        "esri/tasks/query",
        "esri/TimeExtent",
        "dojo/number",
        "dojo/date/locale",
        "dojo/dom",
        "dojo/on",
        "dojo/_base/array",
        "dojo/store/Memory",
        "dgrid/OnDemandGrid",
        "dojo/dom-construct",
        "dojo/domReady!"
      ], function (Map, arcgisUtils, Legend, FeatureLayer, Query, TimeExtent,
        number, locale, dom, on,
        arrayUtils, Memory,
        OnDemandGrid, domConstruct) {
          arcgisUtils.createMap(webmapId, "mapDiv").then(function (response) {
              map = response.map

              var legend = new Legend({
                  map: map,
                  layerInfos: (arcgisUtils.getLegendLayers(response))
              }, "legendDiv");

              legend.startup();
          });

          var sortAttr = [{
              attribute: "name",
              descending: true
          }];
          grid = new OnDemandGrid({
              store: Memory({
                  idProperty: "OBJECTID"
              }),
              columns: {
                  NAME: "NAME",
                  CURRENT_STAGE: "CURRENT STAGE",
                  ALERT_STATUS: "ALERT STATUS",
                  LINK: { label: "Link to Flood Data Image", formatter: makeLink }
              },
              loadingMessage: "Loading data...",
              noDataMessage: "No results found.",
              sort: sortAttr
          }, "grid");

          // create a feature layer
          featureLayer = new FeatureLayer("http://geoweb.cityofsalem.net/salemgis/rest/services/Public/IT_StreamMonitoringStations/MapServer/0", {
              outFields: ["*"]
          });

          // get object IDs from the table (feature layer)
          featureLayer.on("load", function () {
              // create the query to fetch object IDs for earthquakes that have a magnitude greater than 6.0
              // that occurred after January 1st 2007
              var query = new Query();
              query.where = "OBJECTID > 0";
              featureLayer.queryIds(query, function (objectIds) {
                  fetchRecords(objectIds);
              });
          });

          // click listeners for prev/next page buttons
          on(dom.byId("prev"), "click", function () {
              queryRecordsByPage(pageInfo.currentPage - 1);
          });
          on(dom.byId("next"), "click", function () {
              queryRecordsByPage(pageInfo.currentPage + 1);
          });

          // formatting function for numbers
          function formatRound(value) {
              return number.round(value, 2);
          }

          // formatting function for dates
          function formatDate(value) {
              var inputDate = new Date(value);
              return locale.format(inputDate, {
                  selector: "date",
                  datePattern: "MMMM d, y"
              });
          }

          function fetchRecords(objectIds) {
              if (objectIds.length > 0) {
                  updatePageInformation(objectIds);
                  queryRecordsByPage(1);
              } else {
                  grid.showMessage("No matching records");
                  grid.setStore(null);
              }
          }

          function updatePageInformation(objectIds, page) {
              pageInfo = {
                  objectIds: objectIds,
                  totalRecords: objectIds.length,
                  totalPages: Math.ceil(objectIds.length / 15),
                  currentPage: page || 0,
                  recordsPerPage: 15
              };

              dom.byId("pageInfo").innerHTML = pageInfo.currentPage + "/" + pageInfo.totalPages;
              dom.byId("recordsInfo").innerHTML = pageInfo.totalRecords;

              if (pageInfo.currentPage > pageInfo.totalPages) {
                  queryRecordsByPage(pageInfo.currentPage - 1);
              }
          }

          function queryRecordsByPage(pageNumber) {
              // check if the page number is valid
              if (pageNumber < 1 || pageNumber > pageInfo.totalPages) {
                  return;
              }

              //grid.showMessage("Fetching records...");

              var begin = pageInfo.recordsPerPage * (pageNumber - 1);
              var end = begin + pageInfo.recordsPerPage;

              // create the query
              var query = new Query();
              query.objectIds = pageInfo.objectIds.slice(begin, end);
              query.outFields = ["*"];

              // Query for the records with the given object IDs and populate the grid
              featureLayer.queryFeatures(query, function (featureSet) {
                  updateGrid(featureSet, pageNumber);
              });
          }

          function updateGrid(featureSet, pageNumber) {

              var data = arrayUtils.map(featureSet.features, function (entry, i) {
                  return {
                      NAME: entry.attributes.NAME,
                      CURRENT_STAGE: entry.attributes.CURRENT_STAGE,
                      ALERT_STATUS: entry.attributes.ALERT_STATUS,
                      LINK: entry.attributes.LINK
                  };
              });
              grid.store.setData(data);
              grid.refresh();

              // update application state
              pageInfo.currentPage = pageNumber;
              dom.byId("pageInfo").innerHTML = pageInfo.currentPage + "/" + pageInfo.totalPages;
          }

          function makeLink(data) {
            console.log("make link", data);
            return "<a target=\"_blank\" href=\"" + data + "\">" + data + "</a>";
          }

      });
  </script>

  </head>

  <body>
    <div id="mapDiv" style="height: 55%"></div>
    <div id="tbl" style="height:45%">

      <p>
  Total records: 
  <span id="recordsInfo">0</span>
  &nbsp;&nbsp;|&nbsp;&nbsp;

  <button id="prev">Prev Page</button>
  &nbsp;&nbsp<span id="pageInfo"></span>&nbsp;&nbsp

  <button id="next">Next Page</button>
</p>

<!-- dgrid will be created in this div -->
<div id="grid"></div>
    </div>
    <div id="legendDiv"></div>
  </body>
  </html>
share|improve this answer
    
This is fantastic, works perfectly and will be applicable to several other issues I have. Awesome work. –  Neberu Nov 21 '13 at 16:54
    
Glad I could help! –  Derek Swingley Nov 22 '13 at 4:49

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.