Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

In the employee center approval if approver clicks on approve it should pop up the comment box

vinayak_2023
Tera Contributor

In the approval page on employee center if approver click on approve it should pop up the comment box to provide the reason for approval.

I have tried cloning the widgets Todo approvals and Todo Approvals action and added the logic for approve and it is working on the record which are not in the To-do configuration for ex Enhancement, but it is not working for the records which are configured in the To-do configuration example Request and change request. Please help me to work on all the approval records.

4 REPLIES 4

Ankur Bawiskar
Tera Patron
Tera Patron

@vinayak_2023 

share the complete widget code here

💡 If my response helped, please mark it as correct and close the thread 🔒— this helps future readers find the solution faster! 🙏

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Please find the script:

Server Script for the Widget Todos Approval 

(function() {
    var REQUESTED_STATE = "requested";

    if (options && options.sysId) {
        data.approvalId = options.sysId;
        getApprovalInfo(data.approvalId);
        options.useCommentBox = false;

        // Invoke the cloned widget instead of OOB
        data.approvalActionsWidget = $sp.getWidget("todo-approval-actions-change", options);
    }

    function getApprovalInfo(sysId) {
        var sysApprovalRecord = new GlideRecordSecure('sysapproval_approver');
        data.shortDescription = "";
        if (sysApprovalRecord.get(sysId)) {
            data.isPosted = false;
            if (sysApprovalRecord.state.toString() !== REQUESTED_STATE)
                data.isPosted = true;

            if (!gs.nil(sysApprovalRecord.sysapproval) && !gs.nil(sysApprovalRecord.sysapproval.short_description))
                data.shortDescription = sysApprovalRecord.sysapproval.short_description;
            else if (!gs.nil(sysApprovalRecord.document_id))
                data.shortDescription = !gs.nil(sysApprovalRecord.document_id.short_description) ?
                    (sysApprovalRecord.document_id.number + " - " + sysApprovalRecord.document_id.short_description) :
                    sysApprovalRecord.document_id.number;
            else
                data.shortDescription = !gs.nil(sysApprovalRecord.sysapproval) ? sysApprovalRecord.sysapproval.number : "";

            data.approvalText = gs.getMessage("Do you want to approve the following: {0}?", data.shortDescription);
        } else {
            gs.addErrorMessage(gs.getMessage("Unexpected action occurred"));
        }
        return sysApprovalRecord;
    }
})();
Server script for the widget Todos Approval Actions
(function() {
    data.CONST = {
        i18n: {
            PLACEHOLDER_MESSAGE: gs.getMessage("If you are rejecting the request, provide the reason here."),
            REJECT_MODAL_TITLE: gs.getMessage("Reject Request"),
            REJECT_MODAL_MESSAGE: gs.getMessage("Please provide a reason for rejecting the request"),
            REJECT_MODAL_CANCEL: gs.getMessage("Cancel"),
            REJECT_MODAL_SUBMIT: gs.getMessage("Reject Request"),
            REJECT_MODAL_NO_COMMENT_MESSAGE: gs.getMessage("Provide the reason you are rejecting the request in the comments field."),
            APPROVE_MODAL_TITLE: gs.getMessage("Approve Request"),
            APPROVE_MODAL_MESSAGE: gs.getMessage("Please provide a reason for approving the request (optional)"),
           // APPROVE_MODAL_CANCEL: gs.getMessage("Cancel"),
           // APPROVE_MODAL_SUBMIT: gs.getMessage("Approve Request"),
            REAUTH_FAILED_MESSAGE: gs.getMessage('An error occurred during authentication. Please contact your system administrator.')
        },
        ACTION: "updateApprovals",
        REJECT_STATE: "rejected",
        APPROVED_STATE: "approved",
        REQUESTED_STATE: "requested",
        APPROVAL_TABLE: "sysapproval_approver"
    };

    // Get sysId and other options
    data.sysId = input && input.sysId ? input.sysId : options.sysId;
    data.commentId = input && input.commentId ? input.commentId : options.commentId;
    data.commentTable = input && input.commentTable ? input.commentTable : options.commentTable;

    // Force modal behavior for both approve and reject
    data.useCommentBox = false;

    if (data.sysId) {
        var todoApprovalActionsUtil = new sn_ex_sp.TodoApprovalActionsUtil();
        var approvalGr = todoApprovalActionsUtil.getTargetRecord(data.sysId, data.CONST.APPROVAL_TABLE);

        if (!gs.nil(approvalGr)) {
            data.esignRequiredObj = todoApprovalActionsUtil.getEsignObj(approvalGr);
            data.isApprover = todoApprovalActionsUtil.isApprover(approvalGr);

            if (data.isApprover) {
                data.isPosted = false;
                var commentGr = null;

                if (data.commentId && data.commentTable) {
                    commentGr = todoApprovalActionsUtil.getTargetRecord(data.commentId, data.commentTable);
                    if (!gs.nil(commentGr)) {
                        data.requireRejectionComment = todoApprovalActionsUtil.checkRejectionCommentRequired(commentGr);
                    }
                }

                // Only update when client explicitly sends action after modal
                if (input && input.action === data.CONST.ACTION) {
                    input.request.requireRejectionComment = data.requireRejectionComment;
                    input.request.useCommentBox = data.useCommentBox;
                    input.request.comments = input.request.comments || '';

                    // Update approval and comment for both approve and reject
                    data.isPosted = todoApprovalActionsUtil.updateApprovalAndComment(approvalGr, commentGr, input.request);

                    if (data.isPosted && !gs.nil(commentGr)) {
                        setPostApprovalInfo(todoApprovalActionsUtil.getPostApprovalInfo(approvalGr, commentGr));
                    }
                } else if (data.commentId && data.commentTable) {
                    if (approvalGr.state.toString() !== data.CONST.REQUESTED_STATE) {
                        data.isPosted = true;
                        if (!gs.nil(commentGr)) {
                            setPostApprovalInfo(todoApprovalActionsUtil.getPostApprovalInfo(approvalGr, commentGr));
                        }
                    }
                }
            }
        }
    }

    function setPostApprovalInfo(postApprovalInfo) {
        data.caption = postApprovalInfo.caption;
        data.comment = postApprovalInfo.comment;
        data.timestamp = postApprovalInfo.timestamp;
    }
})();
Client controller :
function todosApprovalController($scope, spModal, spAuthModal, $http, spUtil, $log) {
    var c = this;

    $scope.onActionClick = function(state) {
        if (state === c.data.CONST.REJECT_STATE) {
            // Always show modal for reject
            spModal.open({
                title: c.data.CONST.i18n.REJECT_MODAL_TITLE,
                message: c.data.CONST.i18n.REJECT_MODAL_MESSAGE,
                input: true, // Adds text box
                buttons: [{
                        label: c.data.CONST.i18n.REJECT_MODAL_CANCEL,
                        cancel: true
                    },
                    {
                        label: c.data.CONST.i18n.REJECT_MODAL_SUBMIT,
                        primary: true
                    }
                ]
            }).then(function(comment) {
                if (!comment || comment.trim() === '') {
                    spUtil.addErrorMessage(c.data.CONST.i18n.REJECT_MODAL_NO_COMMENT_MESSAGE);
                    return;
                }
                if (c.data.esignRequiredObj.e_sign_required) {
                    openEsignatureModal(state, comment);
                } else {
                    sendUpdateRequest(state, c.data.CONST.ACTION, comment);
                }
            });
        } else if (state === c.data.CONST.APPROVED_STATE) {
    spModal.open({
        title: c.data.CONST.i18n.APPROVE_MODAL_TITLE,
        widget: 'custom-approval-modal',
        buttons: [
            { label: c.data.CONST.i18n.APPROVE_MODAL_CANCEL, cancel: true },
            { label: c.data.CONST.i18n.APPROVE_MODAL_SUBMIT, primary: true }
        ]
    }).then(function(comment) {
        c.data.action = c.data.CONST.ACTION; // Explicitly set action
        sendUpdateRequest(state, c.data.CONST.ACTION, comment || '');
    });
}
        return false;
    };

    function sendUpdateRequest(state, action, comment) {
        c.data.action = action;
        c.data.sysId = c.data.sysId;
        c.data.commentId = c.data.commentId;
        c.data.commentTable = c.data.commentTable;
        c.data.useCommentBox = false; // Force modal behavior
        c.data.request = {
            state: state,
            comments: comment
        };
        c.server.update();
    }

    function openEsignatureModal(state, comment) {
        var requestParams = {
            username: c.data.esignRequiredObj.username,
            userSysId: c.data.esignRequiredObj.userSysId
        };
        spAuthModal.prompt(requestParams, requestParams.username, requestParams.userSysId)
            .then(null, function() {
                alert(c.data.CONST.i18n.REAUTH_FAILED_MESSAGE);
            })
            .then(function() {
                $http.post('/api/sn_ex_sp/approvals/updateState', {
                    sysId: c.data.sysId,
                    commentId: c.data.commentId,
                    commentTable: c.data.commentTable,
                    useCommentBox: false,
                    state: state,
                    comments: comment
                }).then(function(response) {
                    if (response && response.data && response.data.result) {
                        c.getPostApprovalInfo(response.data.result);
                    }
                }, function(reason) {
                    spUtil.addErrorMessage(c.data.CONST.i18n.REAUTH_FAILED_MESSAGE);
                    $log.error(reason);
                });
            });

        c.getPostApprovalInfo = function(result) {
            c.data.isPosted = result.isPosted;
            c.data.caption = result.postApprovalInfo.caption;
            c.data.comment = result.postApprovalInfo.comment;
            c.data.timestamp = result.postApprovalInfo.timestamp;
        };
    }
}


@vinayak_2023 

can you share XMLs of both the customized widget here so that it can be checked in PDI

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Please find the attachments