Hi All,
I'm adapting the "web_one2many_selectable_10" widget in order to make it more flexible. To do it short, this widget displays a checkbox on the left for each record referenced in a one2many field + add a button on top of the list + call an action server side with selected record IDs.
I managed to do what I wanted to with this widget: custom text, custom action defined in the caller template. My problem is, after I called a function server-side, to be able to update the tree view displayed in order to reflect changes made server side.
To do, so I'm trying to refresh only the <tree> node defined in the template for the one2many field displayed with this widget. Up to now, I made it the ugly way by refreshing the whole view (it's not efficient at all) with this javascript call:
self.do_action('reload');
I noticed, this seems to be achievable. Using the "Lot split" button in stock operation ("Operation" tab, when products have lots or serial numbers: opens a pop-up window, you can then register lots or serial numbers and, when you save and close the pop-up, only the tree view in parent view is updated.)
Up to now, I could not figure how the hell this happens and how to call this action from my widget. Help would be much appreciated.
Bellow, the full code.
/*
Usage in templates:
<field name="One2many_name" widget="one2many_selectable" action="server_action" callback="javascript_callback>
If defined, "server_action" will be RPC called and executed by server
If defined, "javascript_callback" will be executed client side after "server_action" is executed server side,
if also defined. "javascript_callback" will be sent results returned from "server_action" if any.
*/
odoo.define('web_one2many_selectable_10.form_widgets', function (require) {
"use strict";
var core = require('web.core');
var _t = core._t;
var Model = require('web.Model');
var FieldOne2Many = core.form_widget_registry.get('one2many');
function executeFunctionByName(functionName, context /*, args */) {
var args = Array.prototype.slice.call(arguments, 2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for (var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
return context[func].apply(context, args);
}
var One2ManySelectable = FieldOne2Many.extend({
template: 'One2ManySelectable',
events: {
'click .web_one2many_selectable': 'button_pressed',
},
multi_selection: true,
// Retrieve options from caller template to have them available in the widget 'One2ManySelectable' template
init: function () {
this._super.apply(this, arguments);
// Default options
this.options = {
caption: 'Apply',
action: null,
callback: null
}
// User defined options from field attributes in caller template
if (arguments[1].attrs.hasOwnProperty('options')) {
this.options = JSON.parse(arguments[1].attrs.options);
}
// Translate caption
this.options.caption = _t(this.options.caption)
},
start: function () {
this._super.apply(this, arguments);
},
// Catch button pressed event, collect IDs, call action server side, then callback client side if defined.
button_pressed: function () {
var self = this;
var selected_ids = self.get_selected_ids_one2many();
if (selected_ids.length === 0) {
this.do_warn(_t("You must choose at least one record."));
return false;
}
// If an action was defined in template, let's call this action server side
if (this.options.action) {
/* Here is a python example function to parse the selected objects
@api.multi
def your_action_name(self):
for record in self:
print record
*/
var model_obj = new Model(this.dataset.model);
model_obj.call(this.options.action, [selected_ids], {context: self.dataset.context})
.then(function (result) {
// If a callback was defined in template, let's call this callback client side with
// results from server call above.
if (self.options.callback) {
executeFunctionByName(self.options.callback, window, result);
} else {
self.do_action('reload');
}
});
}
},
// Collect the object IDs for checked checkboxes
get_selected_ids_one2many: function () {
var ids = [];
this.$el.find('td.o_list_record_selector input:checkbox:checked').closest('tr').each(function () {
ids.push(parseInt($(this).context.dataset.id));
});
return ids;
}
});
// Register this widget
core.form_widget_registry.add('one2many_selectable', One2ManySelectable);
// Make the widget available for other add-ons
return {
One2ManySelectable: One2ManySelectable
}
});
Also tried the bellow instead of do_action('reload'):
var view = self.get_active_view();
view.controller.current_min = 1;
view.controller.reload_content();
without more success.