diff options
| author | Aaron Bohy <aab@odoo.com> | 2020-03-20 13:03:50 +0000 |
|---|---|---|
| committer | Aaron Bohy <aab@odoo.com> | 2020-03-20 13:40:42 +0000 |
| commit | f6c06bd0b87dac11d76a3134eb61c7ef4eb59270 (patch) | |
| tree | 3e029d023fa677ec9b4622d5804af57b562ed51a | |
| parent | 5d86eb64aca928960b3647cd74e5f653dfdf8f8e (diff) | |
[FIX] web: nested x2many with non inline views
Let's assume a form view with an x2many list, containing itself
an x2many field (no widget, so simply displaying the number of
records). When a record of the list is clicked, a form view
opens and displays the same sub x2many field, with widget
many2many_tags. Both list and form views of the x2many aren't
inline (thus have to be fetched on demand).
Before this commit, it crashed when the user clicked on a row
of the x2many list.
The bug has been introduced by a9cebd5a, which wrongly removed the
code handling this specific situation. At least, now we have a
test attesting that this code isn't useless.
Note that the diff isn't as scary as it looks like (we just added
an if/else, and thus indented the former code inside the else
clause).
closes odoo/odoo#48116
Signed-off-by: Géry Debongnie (ged) <ged@openerp.com>
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_view.js | 44 | ||||
| -rw-r--r-- | addons/web/static/tests/fields/relational_fields/field_one2many_tests.js | 28 |
2 files changed, 52 insertions, 20 deletions
diff --git a/addons/web/static/src/js/views/basic/basic_view.js b/addons/web/static/src/js/views/basic/basic_view.js index 6668392b823..140c338d6f6 100644 --- a/addons/web/static/src/js/views/basic/basic_view.js +++ b/addons/web/static/src/js/views/basic/basic_view.js @@ -138,28 +138,32 @@ var BasicView = AbstractView.extend({ // X2Many case: field is an x2many displayed as a list or // kanban view, but the related fields haven't been loaded yet. if ((fieldType === 'one2many' || fieldType === 'many2many')) { - var x2mFieldInfo = record.fieldsInfo[this.viewType][name]; - var viewType = x2mFieldInfo.viewType || x2mFieldInfo.mode; - var knownFields = Object.keys(record.data[name].fieldsInfo[record.data[name].viewType] || {}); - var newFields = Object.keys(record.data[name].fieldsInfo[viewType]); - if (_.difference(newFields, knownFields).length) { + if (!('fieldsInfo' in record.data[name])) { fieldNames.push(name); - } - - if (record.data[name].viewType === 'default') { - // Use case: x2many (tags) in x2many list views - // When opening the x2many record form view, the - // x2many will be reloaded but it may not have - // the same fields (ex: tags in list and list in - // form) so we need to merge the fieldsInfo to - // avoid losing the initial fields (display_name) - var fieldViews = fieldInfo.views || fieldInfo.fieldsInfo || {}; - var defaultFieldInfo = record.data[name].fieldsInfo.default; - _.each(fieldViews, function (fieldView) { - _.each(fieldView.fieldsInfo, function (x2mFieldInfo) { - _.defaults(x2mFieldInfo, defaultFieldInfo); + } else { + var x2mFieldInfo = record.fieldsInfo[this.viewType][name]; + var viewType = x2mFieldInfo.viewType || x2mFieldInfo.mode; + var knownFields = Object.keys(record.data[name].fieldsInfo[record.data[name].viewType] || {}); + var newFields = Object.keys(record.data[name].fieldsInfo[viewType]); + if (_.difference(newFields, knownFields).length) { + fieldNames.push(name); + } + + if (record.data[name].viewType === 'default') { + // Use case: x2many (tags) in x2many list views + // When opening the x2many record form view, the + // x2many will be reloaded but it may not have + // the same fields (ex: tags in list and list in + // form) so we need to merge the fieldsInfo to + // avoid losing the initial fields (display_name) + var fieldViews = fieldInfo.views || fieldInfo.fieldsInfo || {}; + var defaultFieldInfo = record.data[name].fieldsInfo.default; + _.each(fieldViews, function (fieldView) { + _.each(fieldView.fieldsInfo, function (x2mFieldInfo) { + _.defaults(x2mFieldInfo, defaultFieldInfo); + }); }); - }); + } } } // Many2one: context is not the same between the different views diff --git a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js index e93dc2f39ca..4bd23d0d76b 100644 --- a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js +++ b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js @@ -5508,6 +5508,34 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + QUnit.test('nested x2many (non inline views and no widget on inner x2many in list)', async function (assert) { + assert.expect(5); + + this.data.partner.records[0].p = [1]; + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '<form><field name="p"/></form>', + archs: { + 'partner,false,list': '<tree><field name="turtles"/></tree>', + 'partner,false,form': '<form><field name="turtles" widget="many2many_tags"/></form>', + }, + res_id: 1, + }); + + assert.containsOnce(form, '.o_data_row'); + assert.strictEqual(form.$('.o_data_row').text(), '1 record'); + + await testUtils.dom.click(form.$('.o_data_row')); + + assert.containsOnce(document.body, '.modal .o_form_view'); + assert.containsOnce(document.body, '.modal .o_form_view .o_field_many2manytags .badge'); + assert.strictEqual($('.modal .o_field_many2manytags').text().trim(), 'donatello'); + + form.destroy(); + }); + QUnit.test('one2many (who contains display_name) with tree view and without form view', async function (assert) { assert.expect(1); |
