Frappe.confirm not waiting for callback

According to Dialogs Types the Confirm dialog has two callback functions depending on what the user chooses. I have the following code that is supposed to check if the cost center for each accounting entry is “Main” and then confirm they’re happy with this before validating - if they click no then validated is set to false, otherwise the loop continues.

frappe.ui.form.on("Journal Entry", "validate", function(frm) {
    for (i = 0; i < frm.doc.accounts.length; i++) {
	    if (frm.doc.accounts[i].cost_center != "Main") {        
	        continue;
	    }
        frappe.confirm(
	        'The cost center for the entry to <b>' + frm.doc.accounts[i].account + '</b> is <b>' + frm.doc.accounts[i].cost_center + '</b>. Is this correct?',
	        null,
	        function() {
	    	    frappe.validated = false;
	        }
	    )
    }	
});

However, whenever I save a Journal Entry it validates before receiving the response. What is the best way to fix this?

1 Like

If you want an async validate method, return a Promise object.

1 Like
frappe.ui.form.on("Journal Entry", "validate", function(frm) {

    for (i = 0; i < frm.doc.accounts.length; i++) {
        if (frm.doc.accounts[i].cost_center != "Main") {        
            continue;
        }
        
        return new Promise(function(resolve, reject) {
            frappe.confirm(
                'The cost center for the entry to <b>' + frm.doc.accounts[i].account + '</b> is <b>' + frm.doc.accounts[i].cost_center + '</b>. Is this correct?',
                function() {
                    var negative = 'frappe.validated = false';
                    resolve(negative);
                },
                function() {
                    reject();
                }
            )
        })
    }
})

I have changed it to the above which does work, but it only asks about the first entry it finds that matches - as soon as the user responds it either validates the whole document or closes the dialog without validation.

How can I make it so the confirmation happens for each matching instance?

2 Likes

Fixed it, made it an async function and changed return to await. Now it will exit the loop if “No” is selected at any point but continue when “Yes” is chosen until validation.

1 Like

await did not work because I was using frappe.confirm in frappe.call callback. Could solve the issue with following recursion:

frappe.call({
    method: 'python.function',
    args: {},
    callback: function(r) {
        showConfirmDialog(0, r.message.items);
    }
});

function showConfirmDialog(item, items) {
    frappe.confirm(
        "Message"
        function() {
            //YES do something
            showConfirmDialog(item++, items)
        },
        function() {
            //NO do something
            showConfirmDialog(item++, items)
        }
    );
}