[FIX] web: update form widgets when state has changed

Since the <widget> tag is not used anymore in any of our views, it was
not really properly supported. In particular, the form widget was not
notified when the state of the form view has changed, which makes it
very difficult to actually do any useful work.

With this commit, we make sure that the widget method 'updateState' (if
it exists) is called with the new state whenever it changed.

This should allow developers to do useful work without having to work
around the issue. Note that this is not really a perfect solution, since
the updateState methot may or may not have been implemented.

I think that we need some kind of ViewWidget abstraction, which could be
used to have a better and more complete API for widgets in a basic view.
And AbstractField could inherit from ViewWidget.
This commit is contained in:
Géry Debongnie
2018-02-12 10:35:54 +01:00
parent 9e6bc391be
commit e0cb522bf2
2 changed files with 41 additions and 0 deletions
@@ -30,6 +30,7 @@ var BasicRenderer = AbstractRenderer.extend({
this.activeActions = params.activeActions;
this.viewType = params.viewType;
this.mode = params.mode || 'readonly';
this.widgets = [];
},
/**
* This method has two responsabilities: find every invalid fields in the
@@ -95,6 +96,9 @@ var BasicRenderer = AbstractRenderer.extend({
return this._render().then(_.constant([]));
}
// reset all widgets (from the <widget> tag) if any:
_.invoke(this.widgets, 'updateState', state);
var defs = [];
// Reset all the field widgets that are marked as changed and the ones
@@ -605,6 +609,8 @@ var BasicRenderer = AbstractRenderer.extend({
var Widget = widgetRegistry.get(node.attrs.name);
var widget = new Widget(this, record);
this.widgets.push(widget);
// Prepare widget rendering and save the related deferred
var def = widget.__widgetRenderAndInsert(function () {});
if (def.state() === 'pending') {
@@ -6230,6 +6230,41 @@ QUnit.module('Views', {
delete widgetRegistry.map.test;
});
QUnit.test('basic support for widgets', function (assert) {
assert.expect(1);
var MyWidget = Widget.extend({
init: function (parent, dataPoint) {
this.data = dataPoint.data;
},
start: function () {
this.$el.text(this.data.foo + "!");
},
updateState: function (dataPoint) {
this.$el.text(dataPoint.data.foo + "!");
},
});
widgetRegistry.add('test', MyWidget);
var form = createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form string="Partners">' +
'<field name="foo"/>' +
'<widget name="test"/>' +
'</form>',
});
form.$('input[name="foo"]').val("I am alive").trigger('input');
assert.strictEqual(form.$('.o_widget').text(), 'I am alive!',
"widget should have been updated");
form.destroy();
delete widgetRegistry.map.test;
});
QUnit.test('bounce edit button in readonly mode', function (assert) {
assert.expect(3);