Re-render dependent field when another field updated

  • 1
  • Question
  • Updated 4 years ago
  • (Edited)
I'm using a custom renderer to calculate the value for a field based on several other fields (Call them A, B, C). I'd like this field to update dynamically when A B or C is changed.

I put the field in a field editor and gave it a unique id 'avr.'

I've set up the field renderer, and it works the first time.

Then, I set up model actions on the model that contains A B and C, such that if one of them is updated, I run the following skuid snippet:

skuid.component.getById('avr').render();

But the field editor with id='avr' is not re-rendering. At least, the custom renderer doesn't run when I update A B or C.

What's the best way to accomplish this?

I'm basically trying to use skuid to create formula fields that update dynamically in the UI without requiring a save.
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb

Posted 4 years ago

  • 1
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
A quick update:

The model actions are working properly. When I change A, the snippet runs: skuid.component.getById('avr').render();

But the custom renderer doesn't fire.
Photo of Zach McElrath

Zach McElrath, Employee

  • 49,056 Points 20k badge 2x thumb
Matt, can you post your Custom Field Renderer javascript code? Hard to diagnose this without seeing the field renderer code.
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
Sure!

var field = arguments[0],    model = field.model,
    row = field.row,
    mP = skuid.$M('Patient'),
    rP = mP.getFirstRow(),
    value = 0,
$ = skuid.$;
var abortions = Number(rP.Abortions__c) || 0,
    children =  Number(row.Children_Living_with_You__c) || 0;
value += row.In_School__c ? 1 : 0;
value += (rP.Age__c <= 26) ? 1 : 0;
value += row.Financial_Pressure__c ? 1 : 0;
value += (rP.Marital_Status__c != 'Married') ? 1 : 0;
value += row.Parents_In_Favor_of_Abortion__c ? 1 : 0;
value += (row.Father_of_the_Baby_Intention__c == 'Abort') ? 1 : 0;
value += (row.Pregnancy_Intention_on_Intake__c == 'Abort') ? 4 : 0;
value += (children >= 2 && children <= 6) ? 1 : 0;
value += (abortions > 3) ? 3 : abortions;
if (row.AVR_Score__c != value) {
    model.updateRow(row,'AVR_Score__c',value,{initiatorId: field._GUID});
}
skuid.ui.fieldRenderers[field.metadata.displaytype][field.mode](field,value);
var definition;
switch (value) {
    case 0:
    case 1:
        definition = 'Carry to Term';
        break;
    case 2:
    case 3:
    case 4:
        definition = 'Abortion Vulnerable';
        break;
    case 5:
    case 6:
    case 7:
        definition = 'Abortion Minded';
        break;
    default:
        definition = 'Abortion Determined';
}
if (row.Abortion_Vulnerability_Rating__c != definition) {
    model.updateRow(row, {Abortion_Vulnerability_Rating__c: definition});
}

This code works great, when it runs.

I have this action on the same model:
            <action>               <actions>
                  <action type="custom" snippet="renderAVR"/>
               </actions>
               <events>
                  <event>row.updated</event>
               </events>
               <fields>
                  <field>Children_Living_with_You__c</field>
                  <field>Father_of_the_Baby_Intention__c</field>
                  <field>Financial_Pressure__c</field>
                  <field>In_School__c</field>
                  <field>Parents_In_Favor_of_Abortion__c</field>
                  <field>Pregnancy_Intention_on_Intake__c</field>
               </fields>
            </action>
Bascially, when one of the fields required for the avrScore snippet above is updated, I want to run avrScore again.

The renderAVR snippet triggered by the model action (and it is getting triggered) says simply:
skuid.component.getById('avr').render();
I gave the field editor where the field rendered in the avrScore snippet the unique id 'avr'. For some reason the .render() code appears to not cause the field editor to re-render.
(Edited)
Photo of Zach McElrath

Zach McElrath, Employee

  • 49,056 Points 20k badge 2x thumb
Thanks Matt. Can you / have you put some console.log() statements in your Custom Field Renderer to verify that it is / is not being re-run as a result of the Model Actions?
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
I have two custom field renderers that I'm trying to implement this way.

The AVR renderer is not running when I make changes to the fields, even though skuid.component.getById('avr').render(); is running.

The Tension renderer (below) is running on field change, but it's running before skuid.component.getById('tension').render()

When I change one of the fields that impacts tension, I get this in the log:
tensionScore started
tensionScore finished
renderTension run


Here's the tensionScore code:
console.log('tensionScore started');
var field = arguments[0],
    value = 0,
    myLife = 0, 
    badLife = 0,
    shame = 0,
    model = field.model,
    row = field.row,
    mP = skuid.$M('Patient'),
    rP = mP.getFirstRow(),
$ = skuid.$;
// ...
// A BUNCH OF CALCULATIONS TO SET VALUES OF myLife, badLife, shame, and value // ...
model.updateRow(row,'Tension_Score__c',value,{initiatorId: field._GUID});
skuid.ui.fieldRenderers[field.metadata.displaytype][field.mode](field,value);
var tension = [myLife, badLife, shame],
    tensionStrings = ['My Life', 'Bad Life', 'Shame'],
    maximum = [], 
    calculatedTension = '';
$.each(tension, function(i,row){
    if (row == value) {maximum.push(i)}
});
$.each(maximum, function(i,row){
    calculatedTension += tensionStrings[maximum[i]] + ';';
});
if (row.Tension__c != calculatedTension) {
    model.updateRow(row,{Tension__c: calculatedTension});
}
console.log('tensionScore finished');

Interestingly, the Tension__c field is getting updated when this runs, but the Tension_Score__c field is not being updated.
(Edited)
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
Also interestingly, tensionScore runs a lot of times every time a switch tabs, and avrScore runs once. the values of the fields aren't changing, but any models that have changes are being saved when a new tab is selected. This occurs whether or not the fields that are calling the custom renderers are on the tab.



Here are the model actions asking tensionScore to render:

on the PatientCase model (the same model as Tension_Score__c):
<action>               <actions>
                  <action type="custom" snippet="renderTension"/>
               </actions>
               <events>
                  <event>row.updated</event>
               </events>
               <fields>
                  <field>Bad_timing_Doesn_t_fit_my_plans__c</field>
                  <field>Can_t_take_care_of_baby__c</field>
                  <field>In_School__c</field>
                  <field>Pregnancy_Result_of_Infidelity__c</field>
                  <field>Pursuing_a_Career__c</field>
                  <field>Shame_Can_t_tell_X_that_I_m_pregnant__c</field>
                  <field>Strict_Religious_Cultural_Background__c</field>
                  <field>Unemployed__c</field>
               </fields>
            </action>

on the Patient model:
<action>               <actions>
                  <action type="custom" snippet="renderTension"/>
               </actions>
               <events>
                  <event>row.updated</event>
               </events>
               <fields>
                  <field>Ethnicity__c</field>
                  <field>Zip__c</field>
               </fields>
            </action>
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
^bump^
Photo of Matt Sones

Matt Sones, Champion

  • 31,478 Points 20k badge 2x thumb
^bump^ (again)

Any idea why the fields are not re-rendering when I update one of the fields that is used to calculate?