Super cool clone snippet

edited February 10, 2017 in Ideas
So here's the deal, I often have to clone rows in a table via Javascript. Some purist would argue that it should be done via Apex (and I agree), but I've been told to use Javascript. Eventually it was getting annoying to write all of these various snippets for various objects that pretty much did the same thing. I decided to outsource the snippet to a static resource and call it with the various differences passed in as arguments. I registered a snippet called "clone".
// utility snippet for easy cloning of rows. arg[0] = row/model etc. arg[1] = other model api name arg[2] = JS Obj with name -> value pairs 
skuid.snippet.registerSnippet('clone',function(){
//this is beautiful code - JA
console.log(arguments);
var params = arguments[0],
   item = params.item,
   dataRow = params.row,
   dataModel = params.model;
   $ = skuid.$;
   console.log(arguments);
var modelName = arguments[1];//pass in the other model name as the second arg
var customMap = arguments[2] || {};//custom mapping to map in the clone as key-value pairs
if(!modelName){
   console.log("ERROR! You have to pass in the model name as the secong arg");
   return;
}
var newDataModel = skuid.$M(modelName),
   newDataRow = newDataModel.createRow();
var used__r = [];
var rowUpdates = {};
//__r fields are tricky and have to be handled specially
function handle__r(field){
   if(field.indexOf('__r') != -1){
       var api = field.split(".")[0];
       if(used__r.indexOf(api) == -1){
           rowUpdates[api] = dataRow[api];
       }
       used__r.push(api);
   }
}
//update the fields that are actually editable
var allFields = dataModel.fields;
for (var i = 0; i < allFields.length; i++) {
   var apiName = allFields[i].id;
   if(customMap[apiName]){
       rowUpdates[apiName] = customMap[apiName];
   }
   else if(dataRow[apiName]){//if we don't have a value don't bother mapping
       handle__r(apiName);
       rowUpdates[apiName] = dataRow[apiName];
   }
}
//update the row with all of our updates
newDataModel.updateRow(newDataRow, rowUpdates);
newDataModel.save();
});
Then I call this snippet as a row action, on a table.
var params = arguments[0], $ = skuid.$;
var snip = skuid.snippet.getSnippet('clone');
snip(arguments[0], "LiveMP");
"LiveMP" is the model to clone into. If I want it cloned into the same model, I can just pass in the model name itself as the second param. But here's the thing, how do I specify the one or two fields that I want to be different (which is usually what happens when your're cloning something...)??? The answer.... pass in a third parameter of key->value pairs that should be treated differently!! Now everything is awesome. I can call my snippet with a third param.
$('#listInPopup li').dblclick(function(){    $.blockUI({
        message:'Splitting...',
        timeout: 1500
    });
    var selectedCampaign = myObj[$(this).text()];
    var clone = skuid.snippet.getSnippet('clone');
    var modelName = "LiveMP";
    var campaignObj = {
      Campaign__c: selectedCampaign  
    };
    clone(params, modelName, campaignObj);
    skuid.$('.ui-dialog-content').dialog('close');
});
Just wanted to share this, I think it's pretty cool.
3
3 votes

Awaiting Review · Last Updated

Comments

  • Rob HatchRob Hatch 🛠️ 
    edited September 1, 2016
    Thanks for sharing Moshe. 
  • Matt SonesMatt Sones 💎💎💎
    edited February 10, 2017
    Great work as always, Moshe!

    Remove the line "item = params.item," (which you're not using anyway) and you can run this from a pagetitle button as well.

    I added a jquery deferred promise as well, to be able to call your clone function as part of a action framework sequence.
    // utility snippet for easy cloning of rows. arg[0] = row/model etc. arg[1] = other model api name. arg[2] = JS Obj with name -> value pairs  'clone': function(){
    var params = arguments[0],
       dataRow = params.row,
       dataModel = params.model;
       $ = skuid.$,
       dfd = new $.Deferred();
       console.log(arguments);
    var modelName = arguments[1]; //pass in the other model name as the second arg
    var customMap = arguments[2] || {}; //custom mapping to map in the clone as key-value pairs
    if (!modelName) {
       console.log("ERROR! You have to pass in the model name as the secong arg");
       return;
    }
    var newDataModel = skuid.$M(modelName),
       newDataRow = newDataModel.createRow();
    var used__r = [];
    var rowUpdates = {};
    //__r fields are tricky and have to be handled specially
    function handle__r(field){
       if(field.indexOf('__r') != -1){
           var api = field.split(".")[0];
           if(used__r.indexOf(api) == -1){
               rowUpdates[api] = dataRow[api];
           }
           used__r.push(api);
       }
    }
    //update the fields that are actually editable
    var allFields = dataModel.fields;
    for (var i = 0; i < allFields.length; i++) {
       var apiName = allFields[i].id;
       if(customMap[apiName]){
           rowUpdates[apiName] = customMap[apiName];
       }
       else if(dataRow[apiName]){ //if we don't have a value don't bother mapping
           handle__r(apiName);
           rowUpdates[apiName] = dataRow[apiName];
       }
    }
    //update the row with all of our updates
    newDataModel.updateRow(newDataRow, rowUpdates);
    $.when(newDataModel.save())
    .done(function(){
    dfd.resolve();
    })
    .fail(function(){
    dfd.reject();
    console.log('target model of cloned row failed to save.');
    });
    return dfd.promise();
    }
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!