How can I give a confirmation dialog box when I change the workflow state?

I have a workflow defined, now when I click on “Approve” I want to give a frappe.confirm dialog box and if the user clicks the “Yes” then the doc should be approved, if “No” is clicked then the workflow state should remain unchanged.

I have tried do in the following way from the client side-
image

But I couldn’t figure out to stop the change of the workflow, frappe.validated = false doesn’t work
Can someone suggest a way here? Thank You.

I figured it out the below code is working

image

I want to add a confirmation dialogue box for my workflow. Please tell me where do I need to add the code? I have added the following custom script for my doctype.

frappe.ui.form.on(‘Instrument’, {
refresh(frm) {
// your code here
frm.add_custom_button(‘Update Caliberation’, () => {
frappe.prompt({
label: ‘Latest Caliberation Date’,
fieldname: ‘date’,
fieldtype: ‘Date’},

        (values) => {
        // console.log(values.date);

    	var childTable = cur_frm.add_child("instrument_history");
        childTable.type="Calibration"
        childTable.start_date=values.date
        cur_frm.refresh_fields("project_item_list");
    	frm.save()
        });
	});
	
	
	    frm.add_custom_button('Update Prevention', () => {
        frappe.prompt({
        label: 'Latest Prevention Date',
        fieldname: 'date',
        fieldtype: 'Date'}, 
        
        (values) => {
        // console.log(values.date);

    	var childTable = cur_frm.add_child("instrument_history");
        childTable.type="Prevention"
        childTable.start_date=values.date
        cur_frm.refresh_fields("project_item_list");
    	frm.save()
        });
	});
	
}

})

here you need to add the trigger i.e. before_workflow_action: async (frm) => { ....
image
Check out my code above that’s how I used it.
And finally you need to add this line await promise.catch((err) => frappe.throw(err));
If you want to throw some error then add anything in the brackets of reject like reject("You can't Calibrate at this state")

Thanks for sharing Sir.

I have a server-side validation (frappe.throw on Validate method) but it doesn’t shown up after adding this code.
Anything I missed ?

Thanks.
Subhajit

Hello @MSR806 ,
I have very a similar script as you (promise.catch…), everything works perfectly but now after frow call the screen is freezen (all is gray and everything is unclickable). Do you have a same issue, please?

For easier reference…

frappe.ui.form.on('Sales Order', {
before_workflow_action: async (frm) => {
	let promise = new Promise((resolve, reject) => {
	if (frm.doc.workflow_state == "Open") {
		frappe.confirm(
		"<b>Are all fields correctly entered ?</b>",
		() => resolve(),
		() => reject() 
		);
	}
	});
	await promise.catch(() => frappe.throw());
}
})

Hello @wale ,
thanks for the reference, but I am still facing with the freezing problem.
Do you have the same issue with script below, please?

frappe.ui.form.on('Task', {
    before_workflow_action: async (frm) => {
    	let promise = new Promise((resolve, reject) => {
    		frappe.confirm(
    		"<b>Are all fields correctly entered ?</b>",
    		() => resolve(),
    		() => reject() 
    		);
    
    	});
    	await promise.catch(() => frappe.throw());
    }  
});

My result is:

Thanks for response in advance.

Hi @Jiri_Sir

No I haven’t encountered the issue you described. 2 things I’d suggest:

  1. Clear caches (both in bench and in browser)
  2. Try another doctype

It could just be a caching issue in which case, step 1 should solve it. If not, it’ll help to know if it’s peculiar to only some specific doctypes or a general issue

Also ensure your ERP version is updated

Cheers

Hello @wale,
thanks for answer and tips.
I have tried both but nothing helps.

Next I have tried setup a new bench on another pc (iMac) with just frappe app (v. v14.34.0 (version-14)).
Setup worklow on “ToDo” dct and client script (above), but the result is still the same unfortunately :frowning:

I have tried the same client script (on ToDo dct) on site hosted on the frappe.cloud and here the screen is frozen after click “no”.

Hello @Jiri_Sir ,
I have been facing the same issue. It’s basically freezing at the very moment when the dialog is shown.
did you get to solve this issue?

I could figure out the issue. The screen freeze is applied before workflow action and unfreeze after workflow action. So we just need to frappe.dom.unfreeze() before showing dialog and it works.

you can follow below

let promise = new Promise((resolve, reject) =>{
     frappe.dom.unfreeze()

When I click outside the dialog box its gets resolve() and workflow_state changes to “Approved”

This client script works great for me

frappe.ui.form.on('xxx', {
    before_workflow_action: async function (frm) {
            // Return the promise here!
            return new Promise((resolve, reject) => {
                frappe.dom.unfreeze()
                frappe.confirm(
                    `<b>Are you sure you want to <u>${frm.selected_workflow_action}</u>?</b>`,
                    () => resolve(), // Yes → proceed
                    () => reject("❌ Action cancelled by user.") // No → abort transition
                );
            });
    }
});

When working on a KDV Hesaplama (VAT Calculation) tool, you might allow users to change the workflow state—such as switching between calculating VAT included or VAT excluded. To prevent accidental changes, you can add a confirmation dialog box using JavaScript. For example, when a user selects a different calculation mode from a dropdown menu, a confirmation box can appear asking, “Are you sure you want to change the VAT calculation mode?” If the user confirms, the new mode is applied; if not, the selection stays unchanged. This ensures that users don’t accidentally switch modes and end up with incorrect VAT results.