From c2c9df632cd29d97102c8b5a49afae31ca42387f Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Wed, 31 Mar 2021 17:40:22 +0530 Subject: [PATCH] fix: Grid validation - Use separate docfields list for each child table row to avoid cross row validation issue (cherry picked from commit be857c753bf9b721bd18dc881f67ef8d1f9e0e55) --- frappe/public/js/frappe/form/form.js | 20 ++++--- frappe/public/js/frappe/form/grid_row.js | 75 ++++++++++++------------ frappe/public/js/frappe/form/layout.js | 4 +- frappe/public/js/frappe/form/save.js | 5 +- 4 files changed, 52 insertions(+), 52 deletions(-) diff --git a/frappe/public/js/frappe/form/form.js b/frappe/public/js/frappe/form/form.js index c7ed2e4df5..c40838e9f3 100644 --- a/frappe/public/js/frappe/form/form.js +++ b/frappe/public/js/frappe/form/form.js @@ -1075,7 +1075,7 @@ frappe.ui.form.Form = class FrappeForm { } refresh_field(fname) { - if(this.fields_dict[fname] && this.fields_dict[fname].refresh) { + if (this.fields_dict[fname] && this.fields_dict[fname].refresh) { this.fields_dict[fname].refresh(); this.layout.refresh_dependency(); } @@ -1241,20 +1241,22 @@ frappe.ui.form.Form = class FrappeForm { } } - set_df_property(fieldname, property, value, docname, table_field) { - var df; + set_df_property(fieldname, property, value, docname, table_field, table_row_name=null) { + let df; if (!docname || !table_field) { df = this.get_docfield(fieldname); } else { - var grid = this.fields_dict[fieldname].grid, - fname = frappe.utils.filter_dict(grid.docfields, {'fieldname': table_field}); - if (fname && fname.length) - df = frappe.meta.get_docfield(fname[0].parent, table_field, docname); + const grid = this.fields_dict[fieldname].grid; + const filtered_fields = frappe.utils.filter_dict(grid.docfields, {'fieldname': table_field}); + if (filtered_fields.length) { + df = frappe.meta.get_docfield(filtered_fields[0].parent, table_field, table_row_name); + } } if (df && df[property] != value) { df[property] = value; - if (!docname || !table_field) { - // do not refresh childtable fields since `this.fields_dict` doesn't have child table fields + if (table_field && table_row_name) { + this.fields_dict[fieldname].grid.grid_rows_by_docname[table_row_name].refresh_field(fieldname); + } else { this.refresh_field(fieldname); } } diff --git a/frappe/public/js/frappe/form/grid_row.js b/frappe/public/js/frappe/form/grid_row.js index 9fdd4a8e36..bebf46e93d 100644 --- a/frappe/public/js/frappe/form/grid_row.js +++ b/frappe/public/js/frappe/form/grid_row.js @@ -4,9 +4,12 @@ export default class GridRow { constructor(opts) { this.on_grid_fields_dict = {}; this.on_grid_fields = []; + $.extend(this, opts); + if (this.doc) { + this.docfields = frappe.meta.get_docfields(this.parent_df.options, this.doc.name); + } this.columns = {}; this.columns_list = []; - $.extend(this, opts); this.row_check_html = ''; this.make(); } @@ -153,7 +156,7 @@ export default class GridRow { this.render_row(true); } - // refersh form fields + // refresh form fields if(this.grid_form) { this.grid_form.layout && this.grid_form.layout.refresh(this.doc); } @@ -249,27 +252,28 @@ export default class GridRow { this.focus_set = false; this.grid.setup_visible_columns(); - for(var ci in this.grid.visible_columns) { - var df = this.grid.visible_columns[ci][0], - colsize = this.grid.visible_columns[ci][1], - txt = this.doc ? - frappe.format(this.doc[df.fieldname], df, null, this.doc) : - __(df.label); + this.grid.visible_columns.forEach((col, ci) => { + // to get update df for the row + let df = this.docfields.find(field => field.fieldname === col[0].fieldname); + let colsize = col[1]; + let txt = this.doc ? + frappe.format(this.doc[df.fieldname], df, null, this.doc) : + __(df.label); - if(this.doc && df.fieldtype === "Select") { + if (this.doc && df.fieldtype === "Select") { txt = __(txt); } - - if(!this.columns[df.fieldname]) { - var column = this.make_column(df, colsize, txt, ci); + let column; + if (!this.columns[df.fieldname]) { + column = this.make_column(df, colsize, txt, ci); } else { - var column = this.columns[df.fieldname]; + column = this.columns[df.fieldname]; this.refresh_field(df.fieldname, txt); } - // background color for cellz - if(this.doc) { - if(df.reqd && !txt) { + // background color for cell + if (this.doc) { + if (df.reqd && !txt) { column.addClass('error'); } if (column.is_invalid) { @@ -278,7 +282,7 @@ export default class GridRow { column.addClass('bold'); } } - } + }); } make_column(df, colsize, txt, ci) { @@ -403,9 +407,9 @@ export default class GridRow { if (!field.df.onchange_modified) { var field_on_change_function = field.df.onchange; - field.df.onchange = function(e) { + field.df.onchange = (e) => { field_on_change_function && field_on_change_function(e); - me.grid.grid_rows[this.doc.idx - 1].refresh_field(this.df.fieldname); + this.refresh_field(field.df.fieldname); }; field.df.onchange_modified = true; @@ -589,42 +593,37 @@ export default class GridRow { } } refresh_field(fieldname, txt) { - var df = this.grid.get_docfield(fieldname) || undefined; + let df = this.docfields.find(col => { + return col.fieldname === fieldname; + }); // format values if no frm - if(!df) { - df = this.grid.visible_columns.find((col) => { - return col[0].fieldname === fieldname; - }); - if(df && this.doc) { - var txt = frappe.format(this.doc[fieldname], df[0], - null, this.doc); - } + if (df && this.doc) { + txt = frappe.format(this.doc[fieldname], df, null, this.doc); } - if(txt===undefined && this.frm) { - var txt = frappe.format(this.doc[fieldname], df, - null, this.frm.doc); + if (!txt && this.frm) { + txt = frappe.format(this.doc[fieldname], df, null, this.frm.doc); } // reset static value - var column = this.columns[fieldname]; - if(column) { + let column = this.columns[fieldname]; + if (column) { column.static_area.html(txt || ""); - if(df && df.reqd) { - column.toggleClass('error', !!(txt===null || txt==='')); + if (df && df.reqd) { + column.toggleClass('error', !!(txt === null || txt === '')); } } + let field = this.on_grid_fields_dict[fieldname]; // reset field value - var field = this.on_grid_fields_dict[fieldname]; - if(field) { + if (field) { field.docname = this.doc.name; field.refresh(); } // in form - if(this.grid_form) { + if (this.grid_form) { this.grid_form.refresh_field(fieldname); } } diff --git a/frappe/public/js/frappe/form/layout.js b/frappe/public/js/frappe/form/layout.js index d3480b1b75..8b6c627882 100644 --- a/frappe/public/js/frappe/form/layout.js +++ b/frappe/public/js/frappe/form/layout.js @@ -319,7 +319,7 @@ frappe.ui.form.Layout = Class.extend({ fieldobj.doctype = me.doc.doctype; fieldobj.docname = me.doc.name; fieldobj.df = frappe.meta.get_docfield(me.doc.doctype, - fieldobj.df.fieldname, me.frm ? me.frm.doc.name : me.doc.name) || fieldobj.df; + fieldobj.df.fieldname, me.doc.name) || fieldobj.df; // on form change, permissions can change if (me.frm) { @@ -512,7 +512,7 @@ frappe.ui.form.Layout = Class.extend({ if (form_obj) { if (this.doc && this.doc.parent) { form_obj.setting_dependency = true; - form_obj.set_df_property(this.doc.parentfield, property, value, this.doc.parent, fieldname); + form_obj.set_df_property(this.doc.parentfield, property, value, this.doc.parent, fieldname, this.doc.name); form_obj.setting_dependency = false; // refresh child fields this.fields_dict[fieldname] && this.fields_dict[fieldname].refresh(); diff --git a/frappe/public/js/frappe/form/save.js b/frappe/public/js/frappe/form/save.js index 8ac0a0109b..65d84e2202 100644 --- a/frappe/public/js/frappe/form/save.js +++ b/frappe/public/js/frappe/form/save.js @@ -112,7 +112,6 @@ frappe.ui.form.save = function (frm, action, callback, btn) { }; var check_mandatory = function () { - var me = this; var has_errors = false; frm.scroll_set = false; @@ -124,8 +123,8 @@ frappe.ui.form.save = function (frm, action, callback, btn) { $.each(frappe.meta.docfield_list[doc.doctype] || [], function (i, docfield) { if (docfield.fieldname) { - var df = frappe.meta.get_docfield(doc.doctype, - docfield.fieldname, frm.doc.name); + const df = frappe.meta.get_docfield(doc.doctype, + docfield.fieldname, doc.name); if (df.fieldtype === "Fold") { folded = frm.layout.folded;