Magic real time error/warning rendering using javascript snippet on a Table row??

  • 4
  • Question
  • Updated 3 years ago
  • Answered
I want my users to notice right away when they are making a mistake. 

We have a table of Project records, which includes a field showing the amount of revenue we have remaining to recognize. We have another field, "Current Month Estimate," that we use to estimate how much of this remaining revenue we'll be able to recognize this month. 

If we only have $500 remaining to recognize, and a user types in $90,000 in the estimate field, I need something to happen. Since I can't send electrical shocks through salesforce, I am hoping I can use some kind of skuid javascript magic to prevent the user from making this kind of error. 

Validation rules are not an option. 

It would be great if it were a real time error popup or rendering the background of the field red, or preventing a save to that row and showing an error message...

Any ideas?
Photo of Kaede Holland

Kaede Holland

  • 2,744 Points 2k badge 2x thumb
  • happy!!

Posted 5 years ago

  • 4
Photo of Rob Hatch

Rob Hatch, Official Rep

  • 44,006 Points 20k badge 2x thumb
In our next release,  Skuid will be including a new "ElectroZap" component.   Just like rendering conditions,  you dictate the data conditions that activate,  and there are optional properties for how big a jolt it delivers. 

(Oh - its not still April 1st is it? )

Seriously.  In javascript you should be able to evaluate some data condition in real time - and if the condition is true turn on a style.  Maybe the whole page background could turn red,  or a div could be changed from hidden to exposed.  Etc. 

Photo of Zach McElrath

Zach McElrath, Employee

  • 49,056 Points 20k badge 2x thumb
Here is an example I threw together yesterday. I use a Custom Render Snippet on the Amount field on a Table of Opportunities to prevent users from entering an Amount > $1 Billion. If they do, I revert the user's input to whatever value they last entered, and display a red field-level error message.

Here's the end product:



And here's how you do it:

1. add an Inline CSS resource, to define the styles we want to apply to the field when the user's input is bad.

.field-error-messages {    
   color: red;
    padding: 2px;
}
.my-required-field textarea, .my-required-field input  {
    border: 1px solid #D00;
    border-right: 4px solid #D00;
}



2. add a new JavaScript Resource of type Inline (Snippet), called "AmountSanityCheck", with the following Body:

var field = arguments[0],    
   value = skuid.utils.decodeHTML(arguments[1]),
    $ = skuid.$;
    
// Run the default renderer    
skuid.ui.fieldRenderers[field.metadata.displaytype][field.mode](field,value);
if (field.mode === 'edit') {
    
    var errorMessageBox;
    var addFieldError = function(errorMessage) {
        if (!errorMessageBox) {
           errorMessageBox = field.element.find('.field-error-messages');
           if(!errorMessageBox.length) {
               errorMessageBox = $('<div class="field-error-messages">');
               field.element.append(errorMessageBox);
           }
       }
       errorMessageBox.show();
       field.element.addClass('my-required-field');
       errorMessageBox.text(errorMessage);
    };
    
    var input = field.element.find(':input');
    
    var MAX_VALUE = 1000000000;
    var inputValueIsBad = function(inputValue) {
        return parseFloat(inputValue,10)>=MAX_VALUE;
    }
    
    skuid.utils.delayInputCallback(input,function(newValue,oldValue){
        var val = input.val();
       if (inputValueIsBad(input.val())) {
           // Add an error
           addFieldError('Yeah right, a deal for $1B+? Check your numbers dude.');
           // And revert the value
           if (inputValueIsBad(oldValue)) oldValue = 999999999;
           field.model.updateRow(field.row,field.id,oldValue);
           input.val(oldValue);
       }  else {
           if (errorMessageBox) errorMessageBox.hide();
           field.element.removeClass('my-required-field');
       }
    });
}



3. Set your Amount field to use the AmountSanityCheck custom render snippet.




Photo of Nayana Sebastian

Nayana Sebastian

  • 112 Points 100 badge 2x thumb
That worked! Thank you Zach!!
Photo of Nayana Sebastian

Nayana Sebastian

  • 112 Points 100 badge 2x thumb
But the variable oldValue on checkValue(newValue,oldValue) is returning a null value for me.
Photo of Emily Davis

Emily Davis, Employee

  • 3,502 Points 3k badge 2x thumb
Nayana, I think the onChange function actually only takes the new value. In the edit mode renderer, I tried replacing
onChange : function(newValue,oldValue) {
 checkValue(newValue,oldValue);
}

with 
var datePicker = skuid.ui.renderers.DATE.edit({
       value : value,
       onChange : function(newValue) {
          checkValue(newValue,value);
       }
    });

No guarantee that that's the best way to do it, but it captures the old value.
Photo of Fakeha Quazi

Fakeha Quazi

  • 72 Points
Is this delayInputCallback() any method in skuid.utils API?
Photo of Zach McElrath

Zach McElrath, Employee

  • 49,056 Points 20k badge 2x thumb
This method has been added to the skuid.utils API docs.