How to tell which rows have changed in a save

  • 1
  • Question
  • Updated 4 years ago
  • Answered
  • (Edited)
I've tried asking this before. I have a table with 3 rows... one row is changed. When "Save" is clicked I can get a notification if I've registered a field editor...... but I only want to reprocess the 1 saved row... not all three of them.

I've spent a lot of time looking in the console. I see there is a "changes" collection once I make changes... but it seems to be keyed to fields not rows.

I guess I could try and track the changes on each field in each row and then I'd know the row that had changed... but that seems excessive.
Photo of ktyler

ktyler

  • 9,244 Points 5k badge 2x thumb

Posted 4 years ago

  • 1
Photo of Zach McElrath

Zach McElrath, Employee

  • 49,056 Points 20k badge 2x thumb
First of all, the changes property of a skuid.model.Model is an object keyed first by changed row Ids, then by changed field API names.

For instance, if you change the Amount field on one Opportunity row in an Opportunities Model, and changed the StageName and CloseDate field on an Opportunity row in that same Model, here is what that Model's changes property would look like:

{
   '006000000000abcde': {
       'Amount': 50000
   },
   '006000000000747c7': {
       'StageName': 'Closed Won',
       'CloseDate': '2014-06-07'
   }
}

Therefore if you want to check what Rows have been changed, you would just need to examine the keys of the changes object, e.g.

var rowIdsThatChanged = Object.keys(skuid.model.getModel('MyModel').changes);
// returns
// ['006000000000abcde','006000000000747c7']


Now, if you want to be notified each time that a change is made to rows in a model, the most generic way to listen is to use the skuid.events Publish / Subscribe approach (no this is not documented yet, but it will be soon) to subscribe to the row.updated event.

Skuid's Publish / Subscribe event model was introduced in Spring 14 but we have not documented it yet, but it is fully supported. It is much more generic than the skuid.ui.Field / skuid.ui.Editor approaches, which are perfect if you have a specific Row/Field to listen for changes on (skuid.ui.Field), or a specific Model to listen for changes on (skuid.ui.Editor), but are NOT ideal if you want to be more generic.

For example:

skuid.events.subscribe('row.updated',function(changeInfo){
   // First check to make sure we're on the Model we care about
   if ('MyModel' === changeInfo.modelId) {
      // Which row was updated?
      console.log(changeInfo.row);
     // What was its Id?
     console.log(changeInfo.rowId);
     // Which field(s) were just changed?
     console.log(changeInfo.updates);
   }
});


Photo of ktyler

ktyler

  • 9,244 Points 5k badge 2x thumb
Looks great Zach,
I don't want to respond every time any field is changed, only when the row is saved. Is there a corresponding 'row.saved' event i can use with subscribe.

I seem to be stuck, I can write code to trap the updates... and have the row information I need to run my routines.
But when I trap the save, i can no longer tell which rows were saved because after the save the changes object is empty. 

I've tried something like this:
x = new skuid.ui.Editor(skuid.$('#days_table').data('object')) x.registerModel(skuid.model.getModel('Cal_Teacher_Day'));
 x.handleSave = function() {alert('save1'); console.log(skuid.model.getModel('Cal_Teacher_Day').changes); changes = skuid.model.getModel('Cal_Teacher_Day').changes; console.log(Check.string(changes)); change_keys = Object.keys(changes); console.log(change_keys); skuid.ui.Editor.prototype.handleSave.call(x); // Handle the change alert('after save'); }
 
thinking i could see the changes before calling the prototype save, but the object is empty.

I guess I could do a save in a custom button that would let me get to the changed rows and then invoke the save method of the model.

Photo of Zach McElrath

Zach McElrath, Employee

  • 49,056 Points 20k badge 2x thumb
Ken, are you trying to run logic before a save takes place, or after a save has finished?

If before, then yes, you should have a button that runs a custom snippet, so that you can perform pre-save logic, and then call save on your own.

If after, then you can subscribe to the models.saved event, which is fired after any save operation takes place:

skuid.events.subscribe('models.saved',function(saveResult){
    console.log(saveResult);
    console.log(saveResult.models);
    console.log(saveResult.insertResults);
    console.log(saveResult.updateResults);
    console.log(saveResult.deleteResults);
});