Calling validation from the client when custom button is clicked

In my use case, I want to call the DocType validations when my custom button is clicked. The Save button provided by Frappe will be hidden for my use case. How do I invoke the DocType validations explicitly? I tried the frm.trigger(“validate”), but it executes only the Custom Script validations and not the mandatory field validations. How do I invoke all the client side validations?

Hey, I wanna do the same. Could you find a solution?

Kind regards

anyone find a real solution?

From ChatGPT: -

Excellent and very precise question — this touches a subtle but important distinction inside Frappe’s client-side model handling.

Let’s unpack it carefully:


:magnifying_glass_tilted_left: Problem

You’re hiding Frappe’s default Save button, and instead using your own custom button.
You tried:

frm.trigger("validate");

…but that only runs Custom Script “validate” handlers, not Frappe’s built-in form validations (like mandatory fields, invalid data, link checks, etc.).


:white_check_mark: Solution

To invoke all client-side validations (the same ones that run when the built-in Save button is clicked), call:

if (!frm.is_dirty()) {
    frappe.show_alert({ message: __("No changes to save"), indicator: "orange" });
    return;
}

frm.script_manager.trigger("validate").then(() => {
    // now call the built-in validation + save pipeline
    frappe.ui.form.save(frm);
});

But this alone still saves.
If you want only validation (without saving yet), use the same internal method Frappe uses to check before saving:


:light_bulb: Method 1: Run all client-side validations manually (no save)

let validated = true;

try {
    // This runs both built-in and custom validations
    frm.validate();
} catch (e) {
    validated = false;
    console.error(e);
}

if (validated) {
    frappe.msgprint("All validations passed!");
} else {
    frappe.msgprint("Validation failed.");
}

:white_check_mark: frm.validate() runs:

  • Mandatory field checks

  • Link field validity

  • Table child validations

  • Custom Script validate triggers

  • Standard Frappe validation hooks

That’s the same function used internally when you press Save.


:light_bulb: Method 2: Run validation then manually save

If you want to perform something after validation but before saving, for example:

frappe.ui.form.on('Your Doctype', {
    refresh(frm) {
        frm.add_custom_button(__('Custom Save'), async function() {
            try {
                await frm.validate(); // run all client-side validations
                frappe.msgprint("All validations passed. Proceeding to save...");
                await frm.save(); // now save manually
            } catch (e) {
                frappe.msgprint("Validation failed: " + e.message);
            }
        });
    }
});


:gear: Explanation

  • frm.trigger("validate") → only runs custom script event hooks.

  • frm.validate() → runs full validation pipeline used by the native Save button.

  • frm.save() → automatically calls frm.validate() internally, but you can separate them if you need to control the flow.


:brain: Summary

Method What it Runs Saves?
frm.trigger("validate") Custom script validate only :cross_mark:
frm.validate() All client-side validations (same as Save) :cross_mark:
frm.save() Validations + actual save :white_check_mark:

So for your use case (hidden Save button + custom button):

frm.add_custom_button('Validate & Save', async () => {
    try {
        await frm.validate(); // full validation
        await frm.save();     // save if valid
    } catch (e) {
        frappe.msgprint(__('Validation failed: ') + e.message);
    }
});

That’s the exact behavior of the standard Save button — just under your control.


Would you like me to show you how to integrate this cleanly into a custom_button that performs an action without saving, but still respects validation errors (like a “Submit for Review” action)?