diff --git a/addons/web/static/src/js/views/kanban/kanban_record.js b/addons/web/static/src/js/views/kanban/kanban_record.js
index 46f6964dd1c..0f4fc1edd1c 100644
--- a/addons/web/static/src/js/views/kanban/kanban_record.js
+++ b/addons/web/static/src/js/views/kanban/kanban_record.js
@@ -300,6 +300,7 @@ var KanbanRecord = Widget.extend({
// field's widgets point of view
// that dict being shared between records, we don't modify it
// in place
+ var self = this;
var attrs = Object.create(null);
_.each(this.fieldsInfo[field_name], function (value, key) {
if (_.str.startsWith(key, 't-att-')) {
@@ -310,11 +311,12 @@ var KanbanRecord = Widget.extend({
});
var options = _.extend({}, this.options, {attrs: attrs});
var widget = new Widget(this, field_name, this.state, options);
- var def = widget.replace($field);
+ var def = widget.replace($field).then(function () {
+ self._setFieldDisplay(widget.$el, field_name);
+ });
if (def.state() === 'pending') {
this.defs.push(def);
}
- this._setFieldDisplay(widget.$el, field_name);
return widget;
},
_processWidgets: function () {
@@ -324,12 +326,13 @@ var KanbanRecord = Widget.extend({
var Widget = widgetRegistry.get($field.attr('name'));
var widget = new Widget(self, self.state);
- var def = widget._widgetRenderAndInsert(function () {});
+ var def = widget._widgetRenderAndInsert(function () {}).then(function () {
+ widget.$el.addClass('o_widget');
+ $field.replaceWith(widget.$el);
+ });
if (def.state() === 'pending') {
self.defs.push(def);
}
- widget.$el.addClass('o_widget');
- $field.replaceWith(widget.$el);
});
},
/**
diff --git a/addons/web/static/src/js/views/kanban/kanban_renderer.js b/addons/web/static/src/js/views/kanban/kanban_renderer.js
index 3e17c65ef66..268db14c746 100644
--- a/addons/web/static/src/js/views/kanban/kanban_renderer.js
+++ b/addons/web/static/src/js/views/kanban/kanban_renderer.js
@@ -244,7 +244,6 @@ var KanbanRenderer = BasicRenderer.extend({
*/
updateState: function (state) {
this._setState(state);
- this._toggleNoContentHelper();
return this._super.apply(this, arguments);
},
@@ -382,11 +381,8 @@ var KanbanRenderer = BasicRenderer.extend({
var self = this;
var oldWidgets = this.widgets;
this.widgets = [];
- this.$el.empty();
var isGrouped = !!this.state.groupedBy.length;
- this.$el.toggleClass('o_kanban_grouped', isGrouped);
- this.$el.toggleClass('o_kanban_ungrouped', !isGrouped);
var fragment = document.createDocumentFragment();
// render the kanban view
this.defs = [];
@@ -395,15 +391,19 @@ var KanbanRenderer = BasicRenderer.extend({
} else {
this._renderUngrouped(fragment);
}
- this.$el.append(fragment);
- this._toggleNoContentHelper();
var defs = this.defs;
- return this._super.apply(this, arguments).then(function () {
+ delete this.defs;
+ defs.push(this._super.apply(this, arguments));
+ return $.when.apply($, defs).then(function () {
_.invoke(oldWidgets, 'destroy');
+ self.$el.empty();
+ self.$el.toggleClass('o_kanban_grouped', isGrouped);
+ self.$el.toggleClass('o_kanban_ungrouped', !isGrouped);
+ self.$el.append(fragment);
+ self._toggleNoContentHelper();
if (self._isInDom) {
_.invoke(self.widgets, 'on_attach_callback');
}
- return $.when.apply(null, defs);
});
},
/**
diff --git a/addons/web/static/tests/views/kanban_tests.js b/addons/web/static/tests/views/kanban_tests.js
index dbe8e748d33..6310d38fd79 100644
--- a/addons/web/static/tests/views/kanban_tests.js
+++ b/addons/web/static/tests/views/kanban_tests.js
@@ -5133,6 +5133,116 @@ QUnit.module('Views', {
delete fieldRegistry.map.asyncWidget;
});
+ QUnit.test('asynchronous rendering of a field widget with display attr', function (assert) {
+ assert.expect(3);
+
+ var fooFieldDef = $.Deferred();
+ var FieldChar = fieldRegistry.get('char');
+ fieldRegistry.add('asyncwidget', FieldChar.extend({
+ willStart: function () {
+ return fooFieldDef;
+ },
+ start: function () {
+ this.$el.html('LOADED');
+ },
+ }));
+
+ var kanbanController;
+ testUtils.createAsyncView({
+ View: KanbanView,
+ model: 'partner',
+ data: this.data,
+ arch: '' +
+ '
' +
+ '',
+ }).then(function (kanban) {
+ kanbanController = kanban;
+ });
+
+ assert.containsNone(document.body, '.o_kanban_record');
+
+ fooFieldDef.resolve();
+ assert.strictEqual(kanbanController.$('.o_kanban_record').text(),
+ "LOADEDLOADEDLOADEDLOADED");
+ assert.hasClass(kanbanController.$('.o_kanban_record:first .o_field_char'), 'float-right');
+
+ kanbanController.destroy();
+ delete fieldRegistry.map.asyncWidget;
+ });
+
+ QUnit.test('asynchronous rendering of a widget', function (assert) {
+ assert.expect(2);
+
+ var widgetDef = $.Deferred();
+ widgetRegistry.add('asyncwidget', Widget.extend({
+ willStart: function () {
+ return widgetDef;
+ },
+ start: function () {
+ this.$el.html('LOADED');
+ },
+ }));
+
+ var kanbanController;
+ testUtils.createAsyncView({
+ View: KanbanView,
+ model: 'partner',
+ data: this.data,
+ arch: '' +
+ '
' +
+ '',
+ }).then(function (kanban) {
+ kanbanController = kanban;
+ });
+
+ assert.containsNone(document.body, '.o_kanban_record');
+
+ widgetDef.resolve();
+ assert.strictEqual(kanbanController.$('.o_kanban_record .o_widget').text(),
+ "LOADEDLOADEDLOADEDLOADED");
+
+ kanbanController.destroy();
+ delete widgetRegistry.map.asyncWidget;
+ });
+
+ QUnit.test('update kanban with asynchronous field widget', function (assert) {
+ assert.expect(3);
+
+ var fooFieldDef = $.Deferred();
+ var FieldChar = fieldRegistry.get('char');
+ fieldRegistry.add('asyncwidget', FieldChar.extend({
+ willStart: function () {
+ return fooFieldDef;
+ },
+ start: function () {
+ this.$el.html('LOADED');
+ },
+ }));
+
+ var kanban = testUtils.createView({
+ View: KanbanView,
+ model: 'partner',
+ data: this.data,
+ arch: '' +
+ '
' +
+ '',
+ domain: [['id', '=', '0']], // no record matches this domain
+ });
+
+ assert.containsNone(kanban, '.o_kanban_record:not(.o_kanban_ghost)');
+
+ kanban.update({domain: []}); // this rendering will be async
+
+ assert.containsNone(kanban, '.o_kanban_record:not(.o_kanban_ghost)');
+
+ fooFieldDef.resolve();
+
+ assert.strictEqual(kanban.$('.o_kanban_record').text(),
+ "LOADEDLOADEDLOADEDLOADED");
+
+ kanban.destroy();
+ delete widgetRegistry.map.asyncWidget;
+ });
});
});