Select to view content in your preferred language

Editing Related Records

3877
4
04-23-2015 12:46 PM
DavidBuehler
Occasional Contributor III

I am working on phase two of a project that requires users to log progress on a reported incident or concern.  I know it is possible to edit related records via the javascript api as the api has this section on it: Query and edit related records | ArcGIS API for JavaScript .  I also know the collector has this ability, but not all of my users will be in the field needing to update their progress.  I have figured out how most of the example works, but I am not sure how to modify it to get it to what I need it to do.

My goals are to have the users only be able to search for a particular incident by an incident number, then add related records to track their progress on that incident, and finally edit only one field on the feature itself to signify if it is closed.

Below is what I have come up with so far. I am just trying to get the edit a related record to work, by taking the example and modifying it. I know chunks either need to come out or be modified especially part with the "numPeople" to make it work.   Any help or pointers would be greatly appreciated.

<!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>Incident Follow Up Entry</title>


    <link rel="stylesheet" href="http://js.arcgis.com/3.13/dijit/themes/claro/claro.css">
    <link rel="stylesheet" href="http://js.arcgis.com/3.13/esri/css/esri.css">
    <style>   
      html, body {
        height: 100%;
        width: 100%;
        margin: 0; 
        padding: 0;
      }
      body {
        background-color:#fff;
        overflow:hidden;      
      }
      #header{
        border:solid 2px #AAc4c4;
        background:#fff;
        color:#749749;
        border-radius: 4px;
        font-size:14px;
        padding-left:20px;
        font-weight:700;
      }
      #map{
        padding:1px;
        border:solid 2px #AAc4c4;
        border-radius: 4px;
      }
      #leftPane{
        width: 120px;
        border: solid 2px #AAc4c4;
        border-radius: 4px;
      }
      .templatePicker {
        border: none;
      }
      .dj_ie .infowindow .window .top .right .user .content { position: relative; }
      .dj_ie .simpleInfoWindow .content {position: relative;}
    </style>


    <script src="http://js.arcgis.com/3.13/"></script>
    <script>
      var widget;
      var selected;
      var map;
      var updateRelatedRecord; //Was the name voteOnIncident
      
      require([
        "esri/map", 
        "esri/toolbars/edit",
        "esri/graphic",
        "esri/tasks/RelationshipQuery",


        "esri/layers/ArcGISTiledMapServiceLayer",
        "esri/layers/FeatureLayer",


        "esri/symbols/SimpleMarkerSymbol",


        "esri/dijit/editing/Editor",
        "esri/dijit/editing/TemplatePicker",


        "esri/config",
        "esri/request",


        "dojo/_base/array", 
        "esri/Color",
        "dojo/parser", 
        "dojo/dom",


        "dijit/layout/BorderContainer", "dijit/layout/ContentPane", 
        "dojo/domReady!"
      ], function(
        Map, Edit, Graphic, RelationshipQuery,
        ArcGISTiledMapServiceLayer, FeatureLayer,
        SimpleMarkerSymbol,
        Editor, TemplatePicker,
        esriConfig, esriRequest,
        arrayUtils, Color, parser, dom
      ) {
        parser.parse();  


        // refer to "Using the Proxy Page" for more information:  https://developers.arcgis.com/javascript/jshelp/ags_proxy.html
        esriConfig.defaults.io.proxyUrl = "/proxy/";
     
        var map = new Map("map", {
          basemap: "streets",
          center: [-90.173, 44.667],
          zoom: 13
        });


        map.on("layers-add-result", initEditing);
        
        var incidentLayer = new FeatureLayer(".../rest/services/CitizenServiceRequest/CRSRelatedRecords/FeatureServer/0", {
          mode: FeatureLayer.MODE_ONDEMAND,
          outFields: ["*"],
          id: "incidentLayer"
        });


        incidentLayer.setSelectionSymbol(
          new SimpleMarkerSymbol().setColor(new Color("red"))
        );
        map.addLayers([incidentLayer]);


        //working around an arcgis server feature service bug.  Requests to queryRelatedRecords operation fail with feature service 10.
        //Detect if request conatins the queryRelatedRecords operation and then change the source url for that request to the corresponding mapservice
        esriRequest.setRequestPreCallback(function(ioArgs) {
          if (ioArgs.url.indexOf("queryRelatedRecords") !== -1) {
            ioArgs.url = ioArgs.url.replace("FeatureServer", "MapServer");
          }
          return ioArgs;
        });


  function initEditing() {
          map.infoWindow.resize(250,210);
          var incidentLayer = map.getLayer("incidentLayer");
          generateTemplatePicker(incidentLayer);
          map.on("click", function(evt) {
            if (selected) {
//              var currentDate = new Date();
              var incidentAttributes = {
                GENERALISSUE: selected.template.name,
//                req_date:(currentDate.getMonth() + 1) + "/" + currentDate.getDate() + "/" + currentDate.getFullYear(),
//                address: "",
//                district: "",
                STATUS: ""
              };
              var incidentGraphic = new Graphic(evt.mapPoint, selected.symbol, incidentAttributes);
              incidentLayer.applyEdits([incidentGraphic],null,null);
            }
          });
   
          var title, content, graphicAttributes;
          var relatedQuery = new RelationshipQuery();
          relatedQuery.outFields = ["ACTIONTAKEN","ACTIONCOMMENTS","TIMEALLOWANCE","STAFFASSIGNED","STAFFTASK", "UPDATECOMMENTS", "STATUS", "RESOLVEDDATE"];
          relatedQuery.relationshipId = 1;
   
          incidentLayer.on("click", function(evt) {
            graphicAttributes = evt.graphic.attributes;
            title = graphicAttributes.GENERALISSUE;
            content = "<b>Status: </b>" + graphicAttributes.STATUS
                    + "<br><b>Start of Incident: </b>" + graphicAttributes.STARTOFISSUEDATE
  + "<br><b>Private Property Concern: </b>" + graphicAttributes.PRIVATEPROPERTY
  + "<br><b>Public Services Concern: </b>" + graphicAttributes.PUBLICSERVICES
  + "<br><b>Public Streets Concern: </b>" + graphicAttributes.PUBLICSTREETS
  + "<br><b>Public Sidewalks Concern: </b>" + graphicAttributes.PUBLICSIDEWALKS
  + "<br><b>Parks/Zoo/Trails Concern: </b>" + graphicAttributes.PARKSZOOTRAILS
  + "<br><b>Private Signage Concern: </b>" + graphicAttributes.PRIVATESIGNAGE
  + "<br><b>Drainage Conern: </b>" + graphicAttributes.DRAINAGECONCERNS 
  + "<br><b>Unauthorized Dumping Concern: </b>" + graphicAttributes.UNAUTHORIZEDDUMPING
                    + "<br><b>Description: </b>" + graphicAttributes.DESCRIPTION
                    + "<br><b>Contact's First Name: </b>" + graphicAttributes.CFNAME
                    + "<br><b>Contact's Last Name: </b>" + graphicAttributes.CLNAME
                    + "<br><b>Contact's Address: </b>" + graphicAttributes.CADDRESS
                    + "<br><b>Contact's Phone: </b>" + graphicAttributes.CPHONE
                    + "<br><b>Contact's Email: </b>" + graphicAttributes.CEMAIL
                    + "<br><b>Preferred Method of Contact: </b>" + graphicAttributes.CONTACTME;
            
  relatedQuery.REQUESTID = [graphicAttributes.REQUESTID];
            incidentLayer.queryRelatedFeatures(relatedQuery, function(relatedRecords) {
  var followUpRecords = relatedRecords[graphicAttributes.REQUESTID];
//              var fset = relatedRecords[graphicAttributes.objectid];
//              var count = (fset) ? fset.features.length : 0
              
              content = content;  //+ "<br><hr><br><i><span id='numPeople'>" + count + "</span> people think this is important.</i>"
              content = content + "<br><br><img style='cursor:pointer' src='images/thumbsup.jpeg'  onclick='updateRelatedRecord(" + graphicAttributes.REQUESTID + ");'>"; //onclick='voteOnIncident
              map.infoWindow.setTitle(title);
              map.infoWindow.setContent(content);
              map.infoWindow.show(evt.screenPoint, map.getInfoWindowAnchor(evt.screenPoint));
            });
          });
        }

        updateRelatedRecord = function(objectId) {
          var updateRecord = {
            attributes: {
              REQUESTID: REQUESTID,
   ACTIONTAKEN:""
   ACTIONTAKEN:""
   ACTIONCOMMENTS:""
   TIMEALLOWANCE:""
   STAFFASSIGNED:""
   STAFFTASK:""
   UPDATECOMMENTS:""
   STATUS: "Assigned"
            }
          };
          // I have no idea about this? Do I need this?
   var incidentTable = new FeatureLayer(".../rest/services/CitizenServiceRequest/CRSRelatedRecords/FeatureServer/1");
          incidentTable.applyEdits([updateRecord], null, null, 
            function(addResults) {
              var numPeople = dom.byId("numPeople").innerHTML;
              dom.byId("numPeople").innerHTML = parseInt(numPeople, 10) + 1;
            }, function(err){
              alert(err);
            }
          );
        };


        function generateTemplatePicker(layer) {
          console.log("layer", layer);
          widget = new TemplatePicker({
            featureLayers: [ layer ],
            rows: layer.types.length,
            columns: 1,
            grouping: false,
            style: "width:98%;"
          }, "templatePickerDiv");


          widget.startup();


          widget.on("selection-change", function() {
            selected = widget.getSelected();
            console.log("selected", selected);
          });
        }
      });
    </script>
  </head>
  <body class="claro">
    <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="gutters:true, design:'headline'" style="width:100%;height:100%;">
      <div 
0 Kudos
4 Replies
RobertScheitlin__GISP
MVP Emeritus

David,

   I think you forgot to attach your code.

0 Kudos
DavidBuehler
Occasional Contributor III

Sorry about that. Thanks for the catch Robert. The code should be there now.

0 Kudos
DavidBuehler
Occasional Contributor III

Has anyone successfully made a web map that supports not just an up vote using a related records? Or is Collector the way to go until they add that functionality into web app builder or another template?

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

David,

  I have made some comments in your code. Let me know if you any questions:

<!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>Incident Follow Up Entry</title>


    <link rel="stylesheet" href="http://js.arcgis.com/3.13/dijit/themes/claro/claro.css">
    <link rel="stylesheet" href="http://js.arcgis.com/3.13/esri/css/esri.css">
    <style>
      html, body {
        height: 100%;
        width: 100%;
        margin: 0;
        padding: 0;
      }
      body {
        background-color:#fff;
        overflow:hidden;
      }
      #header{
        border:solid 2px #AAc4c4;
        background:#fff;
        color:#749749;
        border-radius: 4px;
        font-size:14px;
        padding-left:20px;
        font-weight:700;
      }
      #map{
        padding:1px;
        border:solid 2px #AAc4c4;
        border-radius: 4px;
      }
      #leftPane{
        width: 120px;
        border: solid 2px #AAc4c4;
        border-radius: 4px;
      }
      .templatePicker {
        border: none;
      }
      .dj_ie .infowindow .window .top .right .user .content { position: relative; }
      .dj_ie .simpleInfoWindow .content {position: relative;}
    </style>


    <script src="http://js.arcgis.com/3.13/"></script>
    <script>
      var widget;
      var selected;
      var map;
      var updateRelatedRecord; //Was the name voteOnIncident

      require([
        "esri/map",
        "esri/toolbars/edit",
        "esri/graphic",
        "esri/tasks/RelationshipQuery",


        "esri/layers/ArcGISTiledMapServiceLayer",
        "esri/layers/FeatureLayer",


        "esri/symbols/SimpleMarkerSymbol",


        "esri/dijit/editing/Editor",
        "esri/dijit/editing/TemplatePicker",


        "esri/config",
        "esri/request",


        "dojo/_base/array",
        "esri/Color",
        "dojo/parser",
        "dojo/dom",


        "dijit/layout/BorderContainer", "dijit/layout/ContentPane",
        "dojo/domReady!"
      ], function(
        Map, Edit, Graphic, RelationshipQuery,
        ArcGISTiledMapServiceLayer, FeatureLayer,
        SimpleMarkerSymbol,
        Editor, TemplatePicker,
        esriConfig, esriRequest,
        arrayUtils, Color, parser, dom
      ) {
        parser.parse();


        // refer to "Using the Proxy Page" for more information:  https://developers.arcgis.com/javascript/jshelp/ags_proxy.html
        esriConfig.defaults.io.proxyUrl = "/proxy/";

        var map = new Map("map", {
          basemap: "streets",
          center: [-90.173, 44.667],
          zoom: 13
        });


        map.on("layers-add-result", initEditing);

        var incidentLayer = new FeatureLayer(".../rest/services/CitizenServiceRequest/CRSRelatedRecords/FeatureServer/0", {
          mode: FeatureLayer.MODE_ONDEMAND,
          outFields: ["*"],
          id: "incidentLayer"
        });


        incidentLayer.setSelectionSymbol(
          new SimpleMarkerSymbol().setColor(new Color("red"))
        );
        map.addLayers([incidentLayer]);


        //working around an arcgis server feature service bug.  Requests to queryRelatedRecords operation fail with feature service 10.
        //Detect if request conatins the queryRelatedRecords operation and then change the source url for that request to the corresponding mapservice
        esriRequest.setRequestPreCallback(function(ioArgs) {
          if (ioArgs.url.indexOf("queryRelatedRecords") !== -1) {
            ioArgs.url = ioArgs.url.replace("FeatureServer", "MapServer");
          }
          return ioArgs;
        });


        function initEditing() {
          map.infoWindow.resize(250,210);
          var incidentLayer = map.getLayer("incidentLayer");
          generateTemplatePicker(incidentLayer);
          map.on("click", function(evt) {
            if (selected) {
//              var currentDate = new Date();
              var incidentAttributes = {
                GENERALISSUE: selected.template.name,
//                req_date:(currentDate.getMonth() + 1) + "/" + currentDate.getDate() + "/" + currentDate.getFullYear(),
//                address: "",
//                district: "",
                STATUS: ""
              };
              var incidentGraphic = new Graphic(evt.mapPoint, selected.symbol, incidentAttributes);
              incidentLayer.applyEdits([incidentGraphic],null,null);
            }
          });

          var title, content, graphicAttributes;
          var relatedQuery = new RelationshipQuery();
          relatedQuery.outFields = ["ACTIONTAKEN","ACTIONCOMMENTS","TIMEALLOWANCE","STAFFASSIGNED","STAFFTASK", "UPDATECOMMENTS", "STATUS", "RESOLVEDDATE"];
          relatedQuery.relationshipId = 1;

          incidentLayer.on("click", function(evt) {
            graphicAttributes = evt.graphic.attributes;
            title = graphicAttributes.GENERALISSUE;
            content = "<b>Status: </b>" + graphicAttributes.STATUS
                    + "<br><b>Start of Incident: </b>" + graphicAttributes.STARTOFISSUEDATE
                    + "<br><b>Private Property Concern: </b>" + graphicAttributes.PRIVATEPROPERTY
                    + "<br><b>Public Services Concern: </b>" + graphicAttributes.PUBLICSERVICES
                    + "<br><b>Public Streets Concern: </b>" + graphicAttributes.PUBLICSTREETS
                    + "<br><b>Public Sidewalks Concern: </b>" + graphicAttributes.PUBLICSIDEWALKS
                    + "<br><b>Parks/Zoo/Trails Concern: </b>" + graphicAttributes.PARKSZOOTRAILS
                    + "<br><b>Private Signage Concern: </b>" + graphicAttributes.PRIVATESIGNAGE
                    + "<br><b>Drainage Conern: </b>" + graphicAttributes.DRAINAGECONCERNS
                    + "<br><b>Unauthorized Dumping Concern: </b>" + graphicAttributes.UNAUTHORIZEDDUMPING
                    + "<br><b>Description: </b>" + graphicAttributes.DESCRIPTION
                    + "<br><b>Contact's First Name: </b>" + graphicAttributes.CFNAME
                    + "<br><b>Contact's Last Name: </b>" + graphicAttributes.CLNAME
                    + "<br><b>Contact's Address: </b>" + graphicAttributes.CADDRESS
                    + "<br><b>Contact's Phone: </b>" + graphicAttributes.CPHONE
                    + "<br><b>Contact's Email: </b>" + graphicAttributes.CEMAIL
                    + "<br><b>Preferred Method of Contact: </b>" + graphicAttributes.CONTACTME;

            relatedQuery.REQUESTID = [graphicAttributes.REQUESTID];
            incidentLayer.queryRelatedFeatures(relatedQuery, function(relatedRecords) {
            var followUpRecords = relatedRecords[graphicAttributes.REQUESTID];
//              var fset = relatedRecords[graphicAttributes.objectid];
//              var count = (fset) ? fset.features.length : 0
//No need to have content = content if you are not adding something to the content on the next line.
//              content = content;  //+ "<br><hr><br><i><span id='numPeople'>" + count + "</span> people think this is important.</i>"
              content = content + "<br><br><img style='cursor:pointer' src='images/thumbsup.jpeg'  onclick='updateRelatedRecord(" + graphicAttributes.REQUESTID + ");'>"; //onclick='voteOnIncident
              map.infoWindow.setTitle(title);
              map.infoWindow.setContent(content);
              map.infoWindow.show(evt.screenPoint, map.getInfoWindowAnchor(evt.screenPoint));
            });
          });
        }

        updateRelatedRecord = function(objectId) {
          var updateRecord = {
            attributes: {
//Not sure where in your code this REQUESTID is suppose to be comming from...
              REQUESTID: REQUESTID,
//All your attributes need a comma seperating them.              
              ACTIONTAKEN:"",
              ACTIONCOMMENTS:"",
              TIMEALLOWANCE:"",
              STAFFASSIGNED:"",
              STAFFTASK:"",
              UPDATECOMMENTS:"",
              STATUS: "Assigned"
            }
          };
          // I have no idea about this? Do I need this?
//Yes you need this, this is how you actually edit the related record. Above you are assgining the new records attributes 
//And now you are going to get a featurelayer to apply the edit to
          var incidentTable = new FeatureLayer(".../rest/services/CitizenServiceRequest/CRSRelatedRecords/FeatureServer/1");
          incidentTable.applyEdits([updateRecord], null, null,
            function(addResults) {
//This is probably the part that you don't need. In the sample this was used to increment the number of people that thought the incident was important in the popup.            
              var numPeople = dom.byId("numPeople").innerHTML;
              dom.byId("numPeople").innerHTML = parseInt(numPeople, 10) + 1;
            }, function(err){
              alert(err);
            }
          );
        };


        function generateTemplatePicker(layer) {
          console.log("layer", layer);
          widget = new TemplatePicker({
            featureLayers: [ layer ],
            rows: layer.types.length,
            columns: 1,
            grouping: false,
            style: "width:98%;"
          }, "templatePickerDiv");

          widget.startup();

          widget.on("selection-change", function() {
            selected = widget.getSelected();
            console.log("selected", selected);
          });
        }
      });
    </script>
  </head>
  <body class="claro">
    <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="gutters:true, design:'headline'" style="width:100%;height:100%;">
      <div data-dojo-type="dijit/layout/ContentPane"  id="header" data-dojo-props="region:'top'">Report a new incident or raise the importance of an existing issue. </div>
      <div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'"></div>
      <div id="leftPane" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'left'">
        <div id="templatePickerDiv"></div>
      </div>
    </div>
  </body>
</html>
0 Kudos