Select to view content in your preferred language

completing an ajax call in onBeforeApplyEdits prior to applyEdits happening

689
2
01-25-2013 11:37 AM
StevenHaslemore
Regular Contributor
Hi there,

I'm attempting to set an id value on any inserts prior to transmission to the server.

I'm listening to the onBeforeApplyEdits event and attempting to complete an ajax call for the next ID value prior to applyEdits happening. The inspector is showing the values after completion but applyEvent is not sending them to the database.

I think I'm not understanding callbacks properly, can anyone point me in the right direction to holding up the applyEvent until my call is complete or trouble shoot my code below?

Thanks very much!
Steven

My code is in a backbone framework but is essentially as follows.

Listens for event on the layer, fires the backbone event listened for elsewhere in the application
dojo.connect(treeEditLayer, 'onBeforeApplyEdits', function(a,u,d){
  console.log('onBeforeApplyEdits called');
  return _this.trigger('BBonBeforeApplyEdits',a,u,d);
});



responds to the backbone event sending the update via the fetchNextId function for an insert.
treeEditView.on("BBonBeforeApplyEdits", function (adds, updates, deletes){
  if (adds)
  {
    flEditHelper.fetchNextId (adds, updates, deletes);  // ajax call to next id, which then calls onBeforeApplyEdits on its succes
    // This will update the inspector but not make it to the database
  }else{
    flEditHelper.onBeforeApplyEdits(adds, updates, deletes); //pass straight to update  - this works fine!
  }
});


in flEditHelper fetchNextId function
fetchNextId: function(a,u,d){
  var tableName = "CITY_TREES";
  var this2 = this;
  var nextId;

  this.xhr = $.ajax({
    url: urlRequest, type: "GET", dataType: "xml", timeout: 5000,
    
    success: function (webResults) {
      console.log('start success - fetchNextId : ' + new Date().getTime());

      nextId = webResults;
      this2.onBeforeApplyEdits(a,u,d,nextId); // then calls onBeforeApplyEdits

      console.log('end success - fetchNextId : ' + new Date().getTime());
    },
    error: function (ex, ey, ez){
      console.log("error");
    },
    complete: function (x){
      console.log("complete: " + x);
    }
  });
}


in flEditHelper onBeforeApplyEdits function
// onBeforeApplyEdits function
onBeforeApplyEdits: function (adds, updates, deletes, nextId){
  console.log('start - onBeforeApplyEdits : ' + new Date().getTime());
  if (adds)
  {
      adds[0].attributes['UNITID'] = nextId;
      adds[0].attributes['GIS_EDITOR'] = esri.id.credentials[0].userId;
  }
  if (updates)
  {
    updates[0].attributes['GIS_EDITOR'] = esri.id.credentials[0].userId;
  }
  console.log('end - onBeforeApplyEdits : ' + new Date().getTime());
}
0 Kudos
2 Replies
DianaBenedict
Frequent Contributor
Steven

You may want to look at creating your own dojo.deferred object.  I am not sure if you will need to first get your id values prior to calling applyedits or do it within the onBeforeApplyEdits function.  In my sample/test app, I am able to btained an ID value from a web service, set the required attributes and then call applyedits ... though theoretically, you should be able to do this within the onBeforeApplyEdits callback.  Eitherway you need to tell the application to wait until you get the response that you need. I have been able to achieve this using the following implementation:

//CODE before I call ApplyEdits but when I need to set the ID value from an Oracle Sequence
    if (updateGraphic.attributes["GNIS_ID"] === null) {
       //returnGazID calls a webservice and returns a deferred object -see code snippet below 
      var deferred = returnGazID();
      deferred.then(function (value) {
        // Do something on success.
        updateGraphic.attributes["GNIS_ID"] = value.StartId;
        editFeatureLayer.applyEdits([updateGraphic], null, null, applyEditsSuccess, applyEditsError);
      }, function (error) {
        //alert("Error: unalble to get GAZ_ID from Web Service, set GNID_ID Value to empty string!");
        // Do something on failure.
        updateGraphic.attributes["GNIS_ID"] = "";
        editFeatureLayer.applyEdits([updateGraphic], null, null, applyEditsSuccess, applyEditsError);
      });
    } else {
      editFeatureLayer.applyEdits([updateGraphic], null, null, applyEditsSuccess, applyEditsError);
    }
.....

//other code in differnt JS file:

function returnGazID() {
  // The parameters to pass to xhrGet, the url, how to handle it, and the callbacks.
  var xhrArgs = {
    url: "http://myserverURLtothewebservice/GazIdGenerator/",
    preventCache: true,
    handleAs: "json",
    load: function (data) {
      //alert("successful call : " + dojo.toJson(data));
    },
    error: function (error) {
      //TODO: add code here to handle error!
      alert("An unexpected error occurred: " + error);
    }
  };

  // Call the asynchronous xhrGet
  var deferred = dojo.xhrGet(xhrArgs);
  return deferred;
}



Like I said, I have not had time to refactor the code but theoretically you should be able to get this to work within the onBeforeApplyEdits but I have had issues with other examples that I have tried within the onBeforeApplyEdits. It just seems like the code continues to applyEdits before I am done with the onBeforeApplyEdits code.  However, this all happened before I used the deferred object.  I believe that with a little "ingenuity" you can get it work with your own deferred object but I am not 100% sure on that.
0 Kudos
StevenHaslemore
Regular Contributor
Hi Diana,

I haven't had any luck trying to hold up the process within the onBeforeApplyEdits callback so will have to go with manually managing the applyEdits much like you have in your example.

Thanks,
Steven
0 Kudos