Event listener for changes in all models

  • 1
  • Question
  • Updated 2 years ago
  • Answered
Hi all,

I've built custom save and cancel buttons on a Skuid page I've built which includes multiple page includes. Right now they both enabled at all times. Ideally I would like to enable the buttons only when at least one of the models detected on the page has unsaved changes as it seems more user-friendly.

Has anyone done something similar? I checked the events documentation, but nothing quite seemed to fit. I'm sure I could hack something together, like using a setInterval function to poll for changes, but I'm wondering if anybody has any better solutions?

Thanks in advance!
Photo of Kathryn Castle

Kathryn Castle

  • 814 Points 500 badge 2x thumb

Posted 2 years ago

  • 1
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
Kathryn,

Here's the full text of the static resource that we use. Hopefully the comments are helpful enough for you to piece it together. Your 'ChangeTracker' model can be on any sObject you want.

// Global Save Buttons Javascript
(function (skuid){
// NOTE: Requires Model named ChangeTracker 
// on the sObject Process_Log__c with 
// Do not load on pageload, 0 rows, create row if none.
//       with ui-only checkbox field called ModelChanges
// Set global buttons to run snippets
// "saveAllSnippet' and 'cancelAllSnippet' (from _General.js)
//   and conditionally enable when ModelChanges is true.
//////////////////////////////////////////////
// Shortcuts & Global Variables //
//////////////////////////////////////////////
var $ = skuid.$,
$e = skuid.events.subscribe,
ChangeTracker;
//////////////////////////////////////////////
// Helper Functions //
//////////////////////////////////////////////
var checkForChanges = function(){
if (ChangeTracker) {
var changes = false;
$.each(skuid.model.map(),function(){
if (this.hasChanged && this.id !== 'ChangeTracker') {
changes = true;
}
});
ChangeTracker.updateRow(ChangeTracker.getFirstRow(), {'ModelChanges': changes});
}
};
//////////////////////////////////////////////
// Subscriptions //
//////////////////////////////////////////////
$e('models.cancelled', checkForChanges);
$e('models.saved', checkForChanges);
$e('row.created', checkForChanges);
$e('row.updated', checkForChanges);
$e('row.deleted', checkForChanges);
$e('row.undeleted', checkForChanges);
//////////////////////////////////////////////
//   Calendar Pageload //
//////////////////////////////////////////////
$(document.body).one('pageload',function(){
ChangeTracker = skuid.$M('ChangeTracker');
});
})(skuid);

And here are the save/cancel snippets that we use:

'saveAllSnippet': function () {
var modelsToSave = [],
dfd = new $.Deferred();
$.each(skuid.model.map(), function(){
//only save changed models that have 'unsaved changes' warning turned on.
if (this.hasChanged && this.preventUnloadIfUnsavedChanges) {
modelsToSave.push(this);
}
});
$.when(skuid.model.save(modelsToSave))
.done(function(){
console.log('All Models Saved.');
dfd.resolve();
})
.fail(function(){
console.log('All Model Save Failed.');
dfd.reject();
});
return dfd.promise();
},
'cancelAllSnippet': function(){
skuid.model.cancel(skuid.model.list());
},
Photo of Kathryn Castle

Kathryn Castle

  • 814 Points 500 badge 2x thumb
Hey Matt, this is really helpful! I do have one question though: since we use page includes, additional models may be loaded onto the page at any time. Do these snippets take that into consideration?
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
Good question. Yes, this accounts for all models, even models added later. I built it for exactly the same reason as you.

I'm thinking about putting out a custom component with this specific functionality. Seems like a global save/cancel would be helpful in a lot of circumstances.
Photo of Kathryn Castle

Kathryn Castle

  • 814 Points 500 badge 2x thumb
Much appreciated! I think a lot of people would get great use of out a global save/cancel custom component.