From 5c704c3d87c2f06197214cc3115ddd7a56aa9e2c Mon Sep 17 00:00:00 2001 From: "stravo1@mac" Date: Fri, 20 Feb 2026 23:14:48 +0530 Subject: [PATCH] fix: has-error respects both invalid and mandatory previously set_invalid would remove (if there was no invalid entry) has-error class which were set by set_mandatory fixes #35789 --- frappe/public/js/frappe/form/controls/base_input.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frappe/public/js/frappe/form/controls/base_input.js b/frappe/public/js/frappe/form/controls/base_input.js index 745ab5f620..db335365c0 100644 --- a/frappe/public/js/frappe/form/controls/base_input.js +++ b/frappe/public/js/frappe/form/controls/base_input.js @@ -277,7 +277,9 @@ frappe.ui.form.ControlInput = class ControlInput extends frappe.ui.form.Control // set has-error if dialog primary button is clicked if (this.layout && this.layout.is_dialog && !this.layout.primary_action_fulfilled) return; - this.$wrapper.toggleClass("has-error", Boolean(this.df.reqd && is_null(value))); + const is_invalid = this.$wrapper.hasClass("has-error-invalid"); + this.$wrapper.toggleClass("has-error-mandatory", Boolean(this.df.reqd && is_null(value))); + this.$wrapper.toggleClass("has-error", is_invalid || Boolean(this.df.reqd && is_null(value))); } set_invalid() { let invalid = !!this.df.invalid; @@ -286,7 +288,9 @@ frappe.ui.form.ControlInput = class ControlInput extends frappe.ui.form.Control this.$input?.toggleClass("invalid", invalid); this.grid_row.columns[this.df.fieldname].is_invalid = invalid; } else { - this.$wrapper.toggleClass("has-error", invalid); + const is_mandatory_and_empty = this.$wrapper.hasClass("has-error-mandatory"); + this.$wrapper.toggleClass("has-error-invalid", invalid); + this.$wrapper.toggleClass("has-error", is_mandatory_and_empty || invalid); } } set_required() {