Display message notifications in Skuid

  • 2
  • Question
  • Updated 4 years ago
  • Answered
Can Skuid display message notifications, like a notification bar at the top of the page, for messages to users, or errors and contain a link that they can click on.

Also if possible, can you close this notification and append further messages to it if needed
Thanks
Photo of Eddie

Eddie

  • 720 Points 500 badge 2x thumb

Posted 4 years ago

  • 2
Photo of Moshe Karmel

Moshe Karmel, Champion

  • 8,646 Points 5k badge 2x thumb
Check out this, specifically the section about handleMessages : http://help.skuidify.com/m/11720/l/20...
Photo of Pablo Martinez

Pablo Martinez

  • 2,468 Points 2k badge 2x thumb
Yes you can: 


The red is with the message error and the orange are message warning (with the handle messages Moshe linked)
Photo of Irvin Waldman

Irvin Waldman, Champion

  • 9,006 Points 5k badge 2x thumb
Hi,  

Very timely question and replies.  There seems to be a caveat with the handleMessages functionality and Multiple Actions.

In the screenshot below, I have a Row Action implemented using the Action Framework.  Here's the workflow:

1. Show a message and block the UI
2. Run a snippet
    a. Invoke a 3rd party web service
    b. All Async
    c. Use handleMessages when error encountered 
    d. Return a promise
3. Save Models
4. Unblock the UI




Here's the snippet:


// Define variable to access snippet's arguments var $ = skuid.$;
var item = arguments[0].item;
var list = arguments[0].list;
var model = arguments[0].model;
var row = item.row;
// Create jQuery Deferred 
var deferred = $.Deferred(); // Handle error messages
var displayMessage = function (message, severity) {
    var topPanel = $('#topPanel');
    var editor = topPanel.data('object').editor;
    editor.handleMessages([
        {
            message: message,
            severity: severity.toUpperCase()
        }
    ]);
}
var onSuccess = function (response) {
    console.log('onSuccess: ' + response);
    var rowsToUpdate = {};
    var respObj = $.parseJSON(response);
    
    if (respObj.Error) {
        displayMessage(respObj.Error.Description, 'ERROR');
    }
    $(respObj.EvaluationError).each(function (i, er) {
        ...
        displayMessage(rowToUpdate.Evaluation_Error__c, 'ERROR');
    });
    $(respObj.EvaluationResult).each(function (i, er) {
        ...
    });
    model.updateRows(rowsToUpdate);

};
var onFailure = function (data) {
    console.log('onFailure: ' + data);
    displayMessage(data, 'ERROR');
};
// Add success and failure handlers
deferred.then(onSuccess, onFailure);
// Assemble JSON request
function buildRequest(row) {
    var request = {
        }
    };
    return request;
}
// Perform web callout
function doWebCallout(request) {
   
    sforce.connection.remoteFunction({
        url: "...",
        requestHeaders: {
            "Content-Type": "application/json",
            //"Connection": "Keep-Alive",
            "Authorization": autToken,
        },
        requestData: JSON.stringify(request),
        method: 'POST',
        onSuccess: function (response) {
            console.log('onSuccess');
            deferred.resolve(response);
        },
        onFailure: function (response) {
            console.log('onSuccess');
            deferred.reject(response);
        }
    });
}
// Assemble the request and perform the callout
doWebCallout(buildRequest(row));
// Return a Promise object
return deferred.promise();


The issue is that the message is never shown and I believe this be due to the async nature of the workflow.

Irvin
(Edited)
Photo of Zach McElrath

Zach McElrath, Employee

  • 49,056 Points 20k badge 2x thumb
Irvin, are you sure that displayMessage is being called? I'd throw in some console.logs into your code right before the points where displayMessage is being called to ensure that your code is getting there --- perhaps the problem is not with handleMessages() , but that handleMessages never gets called.
Photo of Zach McElrath

Zach McElrath, Employee

  • 49,056 Points 20k badge 2x thumb
Irvin, are you sure that displayMessage is being called? I'd throw in some console.logs into your code right before the points where displayMessage is being called to ensure that your code is getting there --- perhaps the problem is not with handleMessages() , but that handleMessages never gets called.
Photo of Irvin Waldman

Irvin Waldman, Champion

  • 9,006 Points 5k badge 2x thumb
Will confirm shortly.  Thanks for the reply.
Photo of Irvin Waldman

Irvin Waldman, Champion

  • 9,006 Points 5k badge 2x thumb
Hi, Yes, my function is being invoked.







var displayMessage = function (message, severity) {   
 console.log('displayMessage: ' + message + ' ' + severity);
    var qliTable = $('#qliTable');
    var editor = qliTable.data('object').editor;
    editor.handleMessages([
        {
            message: message,
            severity: severity.toUpperCase()
        }
    ]);
}
Photo of Irvin Waldman

Irvin Waldman, Champion

  • 9,006 Points 5k badge 2x thumb
Zach,

I think I know this cause of the problem: Save Models action.  

If I remove this action, the messages are shown as expected.

Thoughts?

Regards, Irvin
Photo of Zach McElrath

Zach McElrath, Employee

  • 49,056 Points 20k badge 2x thumb
Aha, that makes sense --- after the "Save Models" action runs, the Model notifies all of its registered Editors of any error messages that happened during the save, if any, and the registered Editors replace their messages with what the Model hands them --- which has the effect here of removing your manually-added messages. 

So what you probably need to do is this: if there are error messages that result from your call to sforce.connection.remoteFunction(), then you need to force the Action Sequence to stop, thereby preventing the Save Models action from being run. To stop the Action Sequence, call deferred.reject() if there are any error messages encountered, like this:

var displayMessages = function (messages) {   
    console.log('displaying ' + messages.length + ' messages');
    var qliTable = $('#qliTable');
    var editor = qliTable.data('object').editor;
    editor.handleMessages(messages);
}

var onSuccess = function (response) {
    console.log('onSuccess: ' + response);

    var rowsToUpdate = {};
    var respObj = $.parseJSON(response);
    var messages = [];

   var addMessage = function(message,severity){
      messages.push({
        message: message,
         severity: severity.toUpperCase()
      });
    };

    if (respObj.Error) {
        addMessage(respObj.Error.Description, 'ERROR');
    }

    $(respObj.EvaluationError).each(function (i, er) {
        ...
        addMessage(rowToUpdate.Evaluation_Error__c, 'ERROR');
    });

    $(respObj.EvaluationResult).each(function (i, er) {
        ...
    });


    // If we have any messages, display them,
    // and stop our Action Sequence from proceeding
    if (messages.length) {
        displayMessages(messages);
       deferred.reject();
    }

    model.updateRows(rowsToUpdate);

};
Photo of Irvin Waldman

Irvin Waldman, Champion

  • 9,006 Points 5k badge 2x thumb
Zach,

Thanks for the timely replies - they keep me moving.

Makes sense.  In my case, the web service could return a response with both successful and unsuccessful results e.g. call out to get a price for 4 products, get back 3 prices and one product not found.

So what I did was set up a model save callback handler that added the messages to the page.  This seems to work.
var quoteModel = skuid.model.getModel('Quote');    
skuid.model.save([model, quoteModel], {
        callback: function(result) {
            if (messages.length > 0) {
                displayMessages(messages);
            }
        }
    });
Photo of Zach McElrath

Zach McElrath, Employee

  • 49,056 Points 20k badge 2x thumb
Glad to hear that helped --- you approach makes sense.