[FIX] web: fix crash on editable list view when moving over a RO field
This is a forward-port of commit https://github.com/odoo/odoo/commit/970387f91fea0cb47404612f7d519ffba2c9ad3b In editable list view, moving to next cell using TAB key crash when the following field is becoming read-only (i.e non-focusable) and an onchange() event is triggered. Consider an editable tree view like this: <form> <field name="o2m" onchange="1"> <tree> <field name="description"/> <field name="date" attrs="{'readonly': [('description', '!=', False)]}"/> <field name="type"/> </tree> </field> </form> 1. Edit 'description' 2. Issue a TAB keypress before 'date' becomes read-only It will crash while calling getSelectionRange() on an empty element. opw-2523630 closes odoo/odoo#71163 X-original-commit: 2a880a8020b55b692505846e9626359fe019dbdb Signed-off-by: Aaron Bohy (aab) <aab@odoo.com> Signed-off-by: Anh Thao PHAM <kitan191@users.noreply.github.com>
This commit is contained in:
@@ -265,7 +265,7 @@ ListRenderer.include({
|
||||
currentWidget = self.allFieldWidgets[currentRowID][self.currentFieldIndex];
|
||||
if (currentWidget) {
|
||||
focusedElement = currentWidget.getFocusableElement().get(0);
|
||||
if (currentWidget.formatType !== 'boolean') {
|
||||
if (currentWidget.formatType !== 'boolean' && focusedElement) {
|
||||
selectionRange = dom.getSelectionRange(focusedElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11771,6 +11771,79 @@ QUnit.module('Views', {
|
||||
|
||||
list.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('edition, then navigation with tab (with a readonly re-evaluated field and onchange)', async function (assert) {
|
||||
// This test makes sure that if we have a cell in a row that will become
|
||||
// read-only after editing another cell, in case the keyboard navigation
|
||||
// move over it before it becomes read-only and there are unsaved changes
|
||||
// (which will trigger an onchange), the focus of the next activable
|
||||
// field will not crash
|
||||
assert.expect(4);
|
||||
|
||||
this.data.bar.onchanges = {
|
||||
o2m: function () {},
|
||||
};
|
||||
this.data.bar.fields.o2m = {string: "O2M field", type: "one2many", relation: "foo"};
|
||||
this.data.bar.records[0].o2m = [1, 4];
|
||||
|
||||
var form = await createView({
|
||||
View: FormView,
|
||||
model: 'bar',
|
||||
res_id: 1,
|
||||
data: this.data,
|
||||
arch: '<form>' +
|
||||
'<group>' +
|
||||
'<field name="display_name"/>' +
|
||||
'<field name="o2m">' +
|
||||
'<tree editable="bottom">' +
|
||||
'<field name="foo"/>' +
|
||||
'<field name="date" attrs="{\'readonly\': [(\'foo\', \'!=\', \'yop\')]}"/>' +
|
||||
'<field name="int_field"/>' +
|
||||
'</tree>' +
|
||||
'</field>' +
|
||||
'</group>' +
|
||||
'</form>',
|
||||
mockRPC: function (route, args) {
|
||||
if (args.method === 'onchange') {
|
||||
assert.step(args.method + ':' + args.model);
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
fieldDebounce: 1,
|
||||
viewOptions: {
|
||||
mode: 'edit',
|
||||
},
|
||||
});
|
||||
|
||||
var jq_evspecial_focus_trigger = $.event.special.focus.trigger;
|
||||
// As KeyboardEvent will be triggered by JS and not from the
|
||||
// User-Agent itself, the focus event will not trigger default
|
||||
// action (event not being trusted), we need to manually trigger
|
||||
// 'change' event on the currently focused element
|
||||
$.event.special.focus.trigger = function () {
|
||||
if (this !== document.activeElement && this.focus) {
|
||||
var activeElement = document.activeElement;
|
||||
this.focus();
|
||||
$(activeElement).trigger('change');
|
||||
}
|
||||
};
|
||||
|
||||
// editable list, click on first td and press TAB
|
||||
await testUtils.dom.click(form.$('.o_data_cell:contains(yop)'));
|
||||
assert.strictEqual(document.activeElement, form.$('tr.o_selected_row input[name="foo"]')[0],
|
||||
"focus should be on an input with name = foo");
|
||||
testUtils.fields.editInput(form.$('tr.o_selected_row input[name="foo"]'), 'new value');
|
||||
var tabEvent = $.Event("keydown", { which: $.ui.keyCode.TAB });
|
||||
await testUtils.dom.triggerEvents(form.$('tr.o_selected_row input[name="foo"]'), [tabEvent]);
|
||||
assert.strictEqual(document.activeElement, form.$('tr.o_selected_row input[name="int_field"]')[0],
|
||||
"focus should be on an input with name = int_field");
|
||||
|
||||
// Restore origin jQuery special trigger for 'focus'
|
||||
$.event.special.focus.trigger = jq_evspecial_focus_trigger;
|
||||
|
||||
assert.verifySteps(["onchange:bar"], "onchange method should have been called");
|
||||
form.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user