Custom Field Renderer - one or the other (depending on field mode)

Greg JarrettGreg Jarrett Member
edited May 2019 in Questions
I have 2 fields for weight/capacity in a model. One is for kilos (kgs), the other is for pounds (lbs). As this is part of a managed package, some users will work in kgs, others will work in lbs. I would prefer not to use conditional rendering of the fields (depending on user location) as sometimes they need to work in both.

I'd also prefer not to use formula fields to do the conversions as it would be great if these conversions could be done in real time, rather than with each save operation.

I've started on a snippet, but am stuck with getting it to work depending on the field mode. What I'd like to do is:

IF Cargo__kgs__c is in edit mode, then update Cargo__lbs__c (which is in read mode) with the converted lbs value, 

otherwise

IF Cargo__lbs__c is in edit mode, then update Cargo__kgs__c (which is in read mode) with the converted kgs value.

image

is this possible? My hacked-together snippet below...

var field = arguments[0],        value = arguments[1];
//runs on the kgs field    
    $ = skuid.$,
    dt = field.metadata.displaytype;

if (field.mode == 'edit') {
    skuid.ui.fieldRenderers[dt][field.mode](field,value);
} else {
    skuid.ui.fieldRenderers[dt].read(field,value);
    
    var m = skuid.model.getModel('CharterOpParent'); 
    var row = m.getFirstRow(); 
    //reference the fields by thier API name
    var lbs = row.stack__Cargo_lbs__c;
    //var kgs = row.stack__Cargo_kgs__c;
    //add all the fields together
    var convert = function() {
    value = (Number(lbs) * 2.2);
    skuid.ui.fieldRenderers[field.metadata.displaytype][field.mode](field,value);
    };
    
    convert();
    
    var listener = new skuid.ui.Field(field.row,field.model,null,{fieldId: 'stack__Cargo_kgs__c'});
    listener.handleChange = function(){
        convert();
    };
    
    field.model.registerField(listener,'stack__Cargo_kgs__c');
    
}

Comments

  • Ben HubbardBen Hubbard Member
    edited May 2019
    Hi Greg,

    I would approach this in a totally different way.  I think a lot of times we jump to the field renderer route when we don't really need to.  (This also has a lot to do with limitations of prior versions of Skuid).  But since we can put action snippets on model events now, and our fields will truly listen and update when a model event happens, we can greatly simplify use cases like yours.  

    In my opinion, what you're trying to do has nothing to do with how your fields render.  Here's what I would do.

    1. Create a new model action on your model that runs a snippet when a row in the model has been updated.

    2. Create a snippet like this...
    var params = arguments[0], $ = skuid.$,
    updates = params.updates,
    convertedWeight;
    if ('skuid__Account_Weight_lbs__c' in updates) {
        convertedWeight = params.row.skuid__Account_Weight_lbs__c / 2.2;
        
        if (convertedWeight) {
            params.model.updateRow(params.row,'skuid__Account_Weight_kg__c',convertedWeight);    
        }
    } else if ('skuid__Account_Weight_kg__c' in updates) {
        convertedWeight = params.row.skuid__Account_Weight_kg__c * 2.2;
        if (convertedWeight) {
            params.model.updateRow(params.row,'skuid__Account_Weight_lbs__c',convertedWeight);    
        }
    }
    Obviously, you'll have to change your fields from skuid__Account_Weight_kg__c to your actual fields.  But this should do the trick.
  • Greg JarrettGreg Jarrett Member
    edited December 2017
    Thanks Ben, this is definitely a much simpler approach! Its working, but only in one direction (ie lbs to kgs or kgs to lbs). When I had it going both ways, Chrome blocks the page and I get the 'aw snap' message.

    I can only think that as the converted field is being updated, it then goes back and updates the other field, which then goes back and updates the converted field again, and so it keeps going.

    Once I commented out the 2nd conversion, the first conversion works fine. See below:
    var params = arguments[0], 
    $ = skuid.$,
    updates = params.updates,
    convertedWeight;
    //kgs to lbs conversion
    if ('stack__Cargo_kgs__c' in updates) {
        convertedWeight = params.row.stack__Cargo_kgs__c * 2.2;
        
        if (convertedWeight) {
            params.model.updateRow(params.row,'stack__Cargo_lbs__c',convertedWeight);    
        }

    /*
    //lbs to kgs conversion
    else if ('stack__Cargo_lbs__c' in updates) {
        convertedWeight = params.row.stack__Cargo_lbs__c / 2.2;
        if (convertedWeight) {
            params.model.updateRow(params.row,'stack__Cargo_kgs__c',convertedWeight);    
        }
    }
    */
    Would the trick be to make it dependent on field mode? (My field editor component is set to read with inline edit). So if lbs.mode = edit, then update kgs, else if kgs.mode = edit, then update lbs
  • Ben HubbardBen Hubbard Member
    edited March 2017
    Hi Greg,

    What version of Skuid are you running?  This should work right in newer versions of Skuid 5.  Older versions will get you stuck in an infinite update loop.
  • Greg JarrettGreg Jarrett Member
    edited December 2017
    Ahhhh. 5.10 in this org. I will have to get my customer to upgrade to the latest release before I could push this out to them. I'll test with a newer version first.
  • Greg JarrettGreg Jarrett Member
    edited December 2017
    Yep that's working really well in 5.21.4   Thanks Ben
Sign In or Register to comment.