From 668dc88c1045cb58aafd61a51a3c05bbff8d2814 Mon Sep 17 00:00:00 2001 From: sokumon Date: Tue, 16 Sep 2025 17:33:41 +0530 Subject: [PATCH] fix: add new row after last field while navigating via keyboard --- .../public/js/frappe/form/controls/table.js | 6 ++++- frappe/public/js/frappe/form/grid.js | 4 ++-- frappe/public/js/frappe/form/grid_row.js | 23 ++++++++++++++++--- frappe/public/scss/common/grid.scss | 10 ++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/frappe/public/js/frappe/form/controls/table.js b/frappe/public/js/frappe/form/controls/table.js index f9a4a142bb..62d31a3f7a 100644 --- a/frappe/public/js/frappe/form/controls/table.js +++ b/frappe/public/js/frappe/form/controls/table.js @@ -24,10 +24,14 @@ frappe.ui.form.ControlTable = class ControlTable extends frappe.ui.form.Control this.grid.grid_rows[row_idx - 1].toggle_editable_row(true); } } else { - if (this.grid.grid_rows.length > 0) + if (this.grid.grid_rows.length > 0) { this.grid.grid_rows[this.grid.grid_rows.length - 1].toggle_editable_row( true ); + } else { + this.grid.add_new_row(null, null, true, null, true); + this.grid.grid_rows[0].toggle_editable_row(true); + } } } }); diff --git a/frappe/public/js/frappe/form/grid.js b/frappe/public/js/frappe/form/grid.js index 62173e480d..0b3c4623d0 100644 --- a/frappe/public/js/frappe/form/grid.js +++ b/frappe/public/js/frappe/form/grid.js @@ -70,7 +70,7 @@ export default class Grid {

-
+
@@ -940,7 +940,7 @@ export default class Grid { setTimeout(() => { this.grid_rows[idx].row - .find('input[type="checkbox"],input[type="Text"],textarea,select') + .find('input[type="Text"],textarea,select') .filter(":visible:first") .focus(); }, 100); diff --git a/frappe/public/js/frappe/form/grid_row.js b/frappe/public/js/frappe/form/grid_row.js index 073d76b97e..10b18171e7 100644 --- a/frappe/public/js/frappe/form/grid_row.js +++ b/frappe/public/js/frappe/form/grid_row.js @@ -12,7 +12,7 @@ export default class GridRow { mandatory: [], read_only: [], }; - this.row_check_html = ''; + this.row_check_html = ''; this.make(); } make() { @@ -343,7 +343,7 @@ export default class GridRow { if (this.doc && !this.grid.df.in_place_edit) { // remove row if (!this.open_form_button) { - this.open_form_button = $('').appendTo(this.row); + this.open_form_button = $('
').appendTo(this.row); if (!this.configure_columns) { const edit_msg = __("Edit", "", "Edit grid row"); @@ -1257,7 +1257,24 @@ export default class GridRow { } // TAB - if (e.which === UP_ARROW) { + if (e.which === TAB && !e.shiftKey) { + var last_column = me.wrapper.find("input:enabled:last").get(0); + var is_last_column = $(this).attr("data-last-input") || last_column === this; + + if (is_last_column) { + // last row + if (me.doc.idx === values.length) { + me.grid.add_new_row(null, null, true); + me.grid.grid_rows[me.grid.grid_rows.length - 1].toggle_editable_row(); + me.grid.set_focus_on_row(); + } else { + // last column before last row + me.grid.grid_rows[me.doc.idx].toggle_editable_row(); + me.grid.set_focus_on_row(me.doc.idx); + return false; + } + } + } else if (e.which === UP_ARROW) { if (me.doc.idx > 1) { var prev = me.grid.grid_rows[me.doc.idx - 2]; if (move_up_down(prev)) { diff --git a/frappe/public/scss/common/grid.scss b/frappe/public/scss/common/grid.scss index 22af86d134..817d337789 100644 --- a/frappe/public/scss/common/grid.scss +++ b/frappe/public/scss/common/grid.scss @@ -1,9 +1,16 @@ +@mixin grid-focus() { + outline: none; + border: 1px solid var(--gray-400) !important; +} .form-grid { border: 1px solid var(--table-border-color); border-radius: var(--border-radius-md); color: var(--text-color); min-height: 150px; background-color: var(--subtle-accent); + &:focus-visible { + @include grid-focus(); + } } .form-grid.error { @@ -687,6 +694,9 @@ display: grid; grid-auto-rows: min-content; border: unset; + &:focus-visible { + @include grid-focus(); + } .grid-static-col.col-xs-1 { flex: 1 0 60px; width: 60px;