[FIX] web: editable list: activate correct field

We have an editable list with 4 fields:
  - fieldA (say boolean)
  - fieldB with readonly modifier, readonly iff fieldA is true
  - fieldC with readonly modifier, readonly iff fieldA is false
  - fieldD

Add a new row to the list: fieldA being false by default, fieldC
is readonly whereas fieldB isn't.

Change the value of fieldA: fieldB becomes readonly, and fieldC is
now editable.

From that point, before this commit, clicking on fieldC activated
fieldD (instead of fieldC).

The bug occurred since 3fd7b20, which added a delay between
the moment fields are re-rendered (and inserted at the end of
allFieldWidgets) and the moment there previous instances are
destroyed (and the new ones take their place in the list). So when
several fields were re-rendered at the same time, the order in
allFieldWidgets could not match the actual column order anymore,
and cause issues like the one described above.

Part of task 2210323

closes odoo/odoo#48039

X-original-commit: 89b9717c08e148ad94db17d8746faa2312b6a07a
Signed-off-by: Michaël Mattiello <mcm-odoo@users.noreply.github.com>
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
Aaron Bohy
2020-03-19 14:59:50 +00:00
parent b42e9c4547
commit 0b88e862a8
2 changed files with 41 additions and 2 deletions
@@ -812,6 +812,9 @@ var BasicRenderer = AbstractRenderer.extend(WidgetAdapterMixin, {
_rerenderFieldWidget: function (widget, record, options) {
// Render the new field widget
var $el = this._renderFieldWidget(widget.__node, record, options);
// get the new widget that has just been pushed in allFieldWidgets
const recordWidgets = this.allFieldWidgets[record.id];
const newWidget = recordWidgets[recordWidgets.length - 1];
const def = this.defs[this.defs.length - 1]; // this is the widget's def, resolved when it is ready
const $div = $('<div>');
$div.append($el); // $el will be replaced when widget is ready (see _renderFieldWidget)
@@ -819,9 +822,9 @@ var BasicRenderer = AbstractRenderer.extend(WidgetAdapterMixin, {
widget.$el.replaceWith($div.children());
// Destroy the old widget and position the new one at the old one's
// (it has been temporarily inserted at the end of the list)
recordWidgets.splice(recordWidgets.indexOf(newWidget), 1);
var oldIndex = this._destroyFieldWidget(record.id, widget);
var recordWidgets = this.allFieldWidgets[record.id];
let newWidget = recordWidgets.pop();
recordWidgets.splice(oldIndex, 0, newWidget);
// Mount new widget if necessary (mainly for Owl components)
@@ -6370,6 +6370,42 @@ QUnit.module('Views', {
list.destroy();
});
QUnit.test('editable list with fields with readonly modifier', async function (assert) {
assert.expect(8);
const list = await createView({
View: ListView,
model: 'foo',
data: this.data,
arch: `
<tree editable="top">
<field name="bar"/>
<field name="foo" attrs="{'readonly': [['bar','=',True]]}"/>
<field name="m2o" attrs="{'readonly': [['bar','=',False]]}"/>
<field name="int_field"/>
</tree>`,
});
await testUtils.dom.click(list.$('.o_list_button_add'));
assert.containsOnce(list, '.o_selected_row');
assert.notOk(list.$('.o_selected_row .o_field_boolean input').is(':checked'));
assert.doesNotHaveClass(list.$('.o_selected_row .o_list_char'), 'o_readonly_modifier');
assert.hasClass(list.$('.o_selected_row .o_list_many2one'), 'o_readonly_modifier');
await testUtils.dom.click(list.$('.o_selected_row .o_field_boolean input'));
assert.ok(list.$('.o_selected_row .o_field_boolean input').is(':checked'));
assert.hasClass(list.$('.o_selected_row .o_list_char'), 'o_readonly_modifier');
assert.doesNotHaveClass(list.$('.o_selected_row .o_list_many2one'), 'o_readonly_modifier');
await testUtils.dom.click(list.$('.o_selected_row .o_field_many2one input'));
assert.strictEqual(document.activeElement, list.$('.o_selected_row .o_field_many2one input')[0]);
list.destroy();
});
QUnit.test('list grouped by date:month', async function (assert) {
assert.expect(1);