Attribute Inspector to Edit Related Tables

3315
3
07-11-2011 08:24 AM
JHayes
by
Occasional Contributor
Hello,

I'm wondering if there's a way to get the Attribute Inspector to edit related tables in the JavaScript API?  We have an application that's creating entries to an SDE geodatabase table.  We'd like to review the entries and edit the content via a new application.  It appears that some combination of the Attribute Inspector and Query Related Records widgets - but since I'm new to web development I'm not sure how to get this done.  I spent several hours attempting to incorporate the Query Related Records code into the Attribute Inspector - but failed to get it up and running.  I'm hoping that someone more experienced can help me out with this.  The Attribute Inspector popup handles coded domains and is ideal for our situation, so getting this tool to edit related tables would be perfect.  The code for the attribute inspector is below.  Adding the Query Related Records code made the post to long, so you can use the link above to access it.

Thanks for your help!!

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=7, IE=9" />
    <!--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>Editable FeatureLayer in Selection Only Mode with Attribute Inspector</title>
    <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/2.4/js/dojo/dijit/themes/claro/claro.css">
    <style>
      html, body { 
        height: 98%; width: 98%; 
        padding: 0;
        overflow:hidden;
      }
      #mapDiv{
        padding:0;
        border: solid 2px #705B35;
      }
      .roundedCorners {
        -moz-border-radius: 4px;
        border-radius: 4px;
      }
      #detailPane{
        height:20px;
        color:#570026;
        font-size:12pt;
        font-weight:600;
        overflow:hidden;
      }
      .dj_ie .infowindow .window .top .right .user .content { position: relative; }
      .dj_ie .simpleInfoWindow .content {position: relative;}

      .esriAttributeInspector {height:100px;}
      .esriAttributeInspector .atiLayerName {display:none;}
      .saveButton {
        padding-left:45px;
         margin:0px;width:16px; height:16px;
       }
    </style>
    
    <script type="text/javascript">var dojoConfig = {parseOnLoad: true};</script>
    <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.4"></script>

    <script type="text/javascript" language="Javascript">
      dojo.require("dijit.layout.BorderContainer");
      dojo.require("dijit.layout.ContentPane");
      dojo.require("esri.map");
      dojo.require("esri.dijit.AttributeInspector-all");


      var map;
      var updateFeature;
      
      function init() {
        //This sample requires a proxy page to handle communications with the ArcGIS Server services. You will need to  
        //replace the url below with the location of a proxy on your machine. See the 'Using the proxy page' help topic 
        //for details on setting up a proxy page.
        esri.config.defaults.io.proxyUrl = "/arcgisserver/apis/javascript/proxy/proxy.ashx";

        var startExtent = new esri.geometry.Extent(-97.5328,37.4344,-97.2582,37.64041, new esri.SpatialReference({wkid:4326}) );

        map = new esri.Map("mapDiv", {extent:esri.geometry.geographicToWebMercator(startExtent)});
        
        dojo.connect(map, "onLoad", function() {
         var resizeTimer;
          dojo.connect(dijit.byId('mapDiv'), 'resize', function() {
            clearTimeout(resizeTimer);
            resizeTimer = setTimeout(function(){
              map.resize();
              map.reposition();
            }, 500);
          });
        });
        
        dojo.connect(map, "onLayersAddResult", initSelectToolbar);
        
        var tiledLayer = new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer");
        map.addLayer(tiledLayer);



        var petroFieldsMSL = new esri.layers.ArcGISDynamicMapServiceLayer("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Petroleum/KSFields/MapServer");
        petroFieldsMSL.setDisableClientCaching(true);
        
        map.addLayer(petroFieldsMSL);



        var petroFieldsFL = new esri.layers.FeatureLayer("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Petroleum/KSFields/FeatureServer/0", {
          mode: esri.layers.FeatureLayer.MODE_SELECTION,
          outFields: ["approxacre","objectid","field_name","activeprod","cumm_oil","cumm_gas","avgdepth"]
        });

        var selectionSymbol = new esri.symbol.SimpleFillSymbol(esri.symbol.SimpleFillSymbol.STYLE_NULL, new esri.symbol.SimpleLineSymbol("dashdot", new dojo.Color("yellow"), 2),null);
        petroFieldsFL.setSelectionSymbol(selectionSymbol);

        dojo.connect(petroFieldsFL, "onEditsComplete", function() {
          petroFieldsMSL.refresh();
        });

        map.addLayers([petroFieldsFL]);
      }



      function initSelectToolbar(results) {

        
        var petroFieldsFL = results[0].layer;
        var selectQuery = new esri.tasks.Query();


        dojo.connect(map, "onClick", function(evt) {
          selectQuery.geometry = evt.mapPoint;
          petroFieldsFL.selectFeatures(selectQuery, esri.layers.FeatureLayer.SELECTION_NEW, function(features) {
            if (features.length > 0) {
             //store the current feature
              updateFeature = features[0];
              map.infoWindow.setTitle(features[0].getLayer().name);
              map.infoWindow.show(evt.screenPoint,map.getInfoWindowAnchor(evt.screenPoint));
            } else {
              map.infoWindow.hide();
            }
          });

        });

        dojo.connect(map.infoWindow, "onHide", function() {
          petroFieldsFL.clearSelection();
        });



        var layerInfos = [{'featureLayer':petroFieldsFL,
           'showAttachments':false,
           'isEditable': true,
           'fieldInfos': [
           {'fieldName': 'activeprod', 'isEditable':true, 'tooltip': 'Current Status', 'label':'Status:'},
           {'fieldName': 'field_name', 'isEditable':true, 'tooltip': 'The name of this oil field', 'label':'Field Name:'},
           {'fieldName': 'approxacre', 'isEditable':false,'label':'Acreage:'},
           {'fieldName': 'avgdepth', 'isEditable':false, 'label':'Average Depth:'},
           {'fieldName': 'cumm_oil', 'isEditable':false, 'label':'Cummulative Oil:'},
           {'fieldName': 'cumm_gas', 'isEditable':false, 'label':'Cummulative Gas:'}
           ]}];

        

        var attInspector = new esri.dijit.AttributeInspector({
          layerInfos:layerInfos
          },
          dojo.create("div")
        );
        
        //add a save button next to the delete button
        var saveButton = new dijit.form.Button({label:"Save","class":"saveButton"});
        dojo.place(saveButton.domNode, attInspector.deleteBtn.domNode, "after");
       
       
        dojo.connect(saveButton,"onClick",function(){
           updateFeature.getLayer().applyEdits(null, [updateFeature], null);         
        });

        
        dojo.connect(attInspector, "onAttributeChange", function(feature,fieldName,newFieldValue) {
          //store the updates to apply when the save button is clicked 
           updateFeature.attributes[fieldName] = newFieldValue;
        });
        
        dojo.connect(attInspector,"onNext",function(feature){
          updateFeature = feature;
          console.log("Next " + updateFeature.attributes.objectid);
        });

        
        dojo.connect(attInspector, "onDelete",function(feature){
          feature.getLayer().applyEdits(null,null,[feature]);
          map.infoWindow.hide();
        });
        
       

        map.infoWindow.setContent(attInspector.domNode);
        map.infoWindow.resize(325,210);


      }

      dojo.addOnLoad(init);

    </script>
  </head>
  
  <body class="claro">
    <div data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design:'headline', gutters:false" style="width:100%;height:100%;">
      <div id="detailPane" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'top'">
        Click a field to display the attribute inspector with customized fields.
      </div>
      <div data-dojo-type="dijit.layout.ContentPane" class="roundedCorners" data-dojo-props="region:'center'" id="mapDiv"></div>
    </div>
  </body>
</html>
3 Replies
LukeBehling
Occasional Contributor
Joe,
Did you ever get this working? I am trying to do the same thing and having some difficulties.

Thanks,
Luke
0 Kudos
DianaBenedict
Occasional Contributor III
Yes, it is possible to edit related records using the Attribute inspector. I do not have the code with me (since I am at home) but I essentially walk you through the workflow. The workflow does not "take advantage" of the ESRI relationship classes since my schema does not use them.
1) add the FeatureService layer for your feature class to edit as you did in your example code
(var petroFieldsFL = new esri.layers.FeatureLayer ...)
2) add the related table also as a FeatureLayer to the map
3) hookup your OnLayersAddResult and create your attributeInspector objects.
4) you will need 2 attribute inspector objects one for the feature class and a second for the related table
5) create two divs to hold each attribute inspector
6) create a "select features' button or use your map onClick event for selecting the features of interest
7) call the code to select features. the example is taken from your code. Note that you are using an anonymous function to process your selection. I went ahead and added pseudocode to select from the realtedTable featureLayer.
petroFieldsFL.selectFeatures(selectQuery, esri.layers.FeatureLayer.SELECTION_NEW, function(features) {
     if (features.length > 0) {
       //store the current feature
       updateFeature = features[0];
      //TODO: add code here to select from the related table....
      var newQuery = ....
      newQuery.where = //add your where clause here based on your updateFeature .attributes["myIDField'] value 
      myRelatedTable..selectFeatures(newQuery, esri.layers.FeatureLayer.SELECTION_NEW, function(records) {

       }
       map.infoWindow.setTitle(features[0].getLayer().name);
       map.infoWindow.show(evt.screenPoint,map.getInfoWindowAnchor(evt.screenPoint));
     } else {
        map.infoWindow.hide();
     }
});

😎 Note that the AttributeInspector displays the selected records for the Layers that you indicated in the LayerInfos when you instantiated the object.  That is why you will want 2 different attribute inspectors
9) after everything is selected then you can go ahead and show your info window. (note you might want to play with this code .. do you wait to show the info window only after you have selected from the related table? or do you show it right away .. after you have selected from the feature class? your call...
10) once you have gotten it working correctly with the 1st record in your selection (features[0]) then you will need to hook up/ update the attInspector "onNext"  event to select the related record from the next record.

Hope that makes sense. Again, remember that the AttributeInspector works on the selected records from your LayerInfos that you set up.  I almost always use myFeatureLayer.selectfeatures, and then open or display the content that holds the attributeInspector
0 Kudos
TraciMeulemans
New Contributor II
Diana,

Is it possible for you to post your code for this?

Thanks,

Traci
0 Kudos