[FIX] web: renderers with a pie chart can reload

The on_attach_callback methods on the widgets (comming from a tag
'widget') of a form renderer were not called at an appropriate time.
They were not called at all or called before the widgets were actually
in the dom. This was made manifest in the dashboards that generally use
pie charts widgets. Each time a pie chart widget is renderered,
a new canvas with a unique id is created. The above mentioned problem
explains why Chart.js was not able to acquire the canvas contexts: they
are obtained by looking for a specific id in the dom.

The present commit fixes that problem by doing in the class FormRenderer
what was already done correctly in the child class DashboardRenderer and
remove the unapropriate calls to on_attach_callback in _renderWidget.

Task ID: 2278717

closes odoo/odoo#53853

X-original-commit: 7641c7074616b4375f1eb4f1fcb5a96e2ed39f94
Related: odoo/enterprise#11537
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
Mathieu Duckerts-Antoine
2020-06-30 09:12:11 +00:00
parent a80ace5654
commit 141aaa2db1
3 changed files with 29 additions and 3 deletions
@@ -802,9 +802,6 @@ var BasicRenderer = AbstractRenderer.extend(WidgetAdapterMixin, {
self._registerModifiers(node, record, widget);
widget.$el.addClass('o_widget');
$el.replaceWith(widget.$el);
if (self._isInDom && widget.on_attach_callback) {
widget.on_attach_callback();
}
});
return $el;
@@ -55,6 +55,7 @@ var FormRenderer = BasicRenderer.extend(WidgetAdapterMixin, {
on_attach_callback: function () {
WidgetAdapterMixin.on_attach_callback.call(this);
this._isInDom = true;
_.invoke(this.widgets, 'on_attach_callback');
this._super.apply(this, arguments);
},
/**
@@ -1010,6 +1011,7 @@ var FormRenderer = BasicRenderer.extend(WidgetAdapterMixin, {
_.forEach(self.allFieldWidgets, function (widgets){
_.invoke(widgets, 'on_attach_callback');
});
_.invoke(self.widgets, 'on_attach_callback');
}
}).guardedCatch(function () {
$form.remove();
@@ -9294,6 +9294,33 @@ QUnit.module('Views', {
form.destroy();
});
QUnit.test('reload a form view with a pie chart does not crash', async function (assert) {
assert.expect(3);
const form = await createView({
View: FormView,
model: 'partner',
data: this.data,
arch: `<form>
<widget name="pie_chart" title="qux by product" attrs="{'measure\': 'qux', 'groupby': 'product_id'}"/>
</form>`,
});
assert.containsOnce(form, '.o_widget');
const canvasId1 = form.el.querySelector('.o_widget canvas').id;
await form.reload();
await testUtils.nextTick();
assert.containsOnce(form, '.o_widget');
const canvasId2 = form.el.querySelector('.o_widget canvas').id;
// A new canvas should be found in the dom
assert.notStrictEqual(canvasId1, canvasId2);
form.destroy();
delete widgetRegistry.map.test;
});
});
});