diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js
index 8a58dec13ec..9bd1916d714 100644
--- a/addons/web/static/src/js/view_form.js
+++ b/addons/web/static/src/js/view_form.js
@@ -242,69 +242,95 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView#
$pager.find('span.oe_pager_index').html(index);
$pager.find('span.oe_pager_count').html(this.dataset.ids.length);
},
+ parse_on_change: function (on_change, widget) {
+ var self = this;
+ var onchange = _.str.trim(on_change);
+ var call = onchange.match(/^\s?(.*?)\((.*?)\)\s?$/);
+ if (!call) {
+ return null;
+ }
+
+ var method = call[1];
+ if (!_.str.trim(call[2])) {
+ return {method: method, args: [], context_index: null}
+ }
+
+ var argument_replacement = {
+ 'False': function () {return false;},
+ 'True': function () {return true;},
+ 'None': function () {return null;},
+ 'context': function (i) {
+ context_index = i;
+ var ctx = widget.build_context ? widget.build_context() : {};
+ return ctx;
+ }
+ };
+ var parent_fields = null, context_index = null;
+ var args = _.map(call[2].split(','), function (a, i) {
+ var field = _.str.trim(a);
+
+ // literal constant or context
+ if (field in argument_replacement) {
+ return argument_replacement[field](i);
+ }
+ // form field
+ if (self.fields[field]) {
+ var value = self.fields[field].get_on_change_value();
+ return value == null ? false : value;
+ }
+ // parent field
+ var splitted = field.split('.');
+ if (splitted.length > 1 && _.str.trim(splitted[0]) === "parent" && self.dataset.parent_view) {
+ if (parent_fields === null) {
+ parent_fields = self.dataset.parent_view.get_fields_values();
+ }
+ var p_val = parent_fields[_.str.trim(splitted[1])];
+ if (p_val !== undefined) {
+ return p_val == null ? false : p_val;
+ }
+ }
+ // string literal
+ var first_char = field[0], last_char = field[field.length-1];
+ if ((first_char === '"' && last_char === '"')
+ || (first_char === "'" && last_char === "'")) {
+ return field.slice(1, -1);
+ }
+
+ throw new Error("Could not get field with name '" + field +
+ "' for onchange '" + onchange + "'");
+ });
+
+ return {
+ method: method,
+ args: args,
+ context_index: context_index
+ };
+ },
do_onchange: function(widget, processed) {
var self = this;
var act = function() {
try {
- processed = processed || [];
- if (widget.node.attrs.on_change) {
- var onchange = _.str.trim(widget.node.attrs.on_change);
- var call = onchange.match(/^\s?(.*?)\((.*?)\)\s?$/);
- if (call) {
- var method = call[1], args = [];
- var context_index = null;
- var argument_replacement = {
- 'False' : function() {return false;},
- 'True' : function() {return true;},
- 'None' : function() {return null;},
- 'context': function(i) {
- context_index = i;
- var ctx = widget.build_context ? widget.build_context() : {};
- return ctx;
- }
- };
- var parent_fields = null;
- _.each(call[2].split(','), function(a, i) {
- var field = _.str.trim(a);
- if (field in argument_replacement) {
- args.push(argument_replacement[field](i));
- return;
- } else if (self.fields[field]) {
- var value = self.fields[field].get_on_change_value();
- args.push(value == null ? false : value);
- return;
- } else {
- var splitted = field.split('.');
- if (splitted.length > 1 && _.str.trim(splitted[0]) === "parent" && self.dataset.parent_view) {
- if (parent_fields === null) {
- parent_fields = self.dataset.parent_view.get_fields_values();
- }
- var p_val = parent_fields[_.str.trim(splitted[1])];
- if (p_val !== undefined) {
- args.push(p_val == null ? false : p_val);
- return;
- }
- }
- }
- throw "Could not get field with name '" + field +
- "' for onchange '" + onchange + "'";
- });
- var ajax = {
- url: '/web/dataset/call',
- async: false
- };
- return self.rpc(ajax, {
- model: self.dataset.model,
- method: method,
- args: [(self.datarecord.id == null ? [] : [self.datarecord.id])].concat(args),
- context_id: context_index === null ? null : context_index + 1
- }).pipe(function(response) {
- return self.on_processed_onchange(response, processed);
- });
- } else {
- console.warn("Wrong on_change format", on_change);
+ processed = processed || [];
+ var on_change = widget.node.attrs.on_change;
+ if (on_change) {
+ var change_spec = self.parse_on_change(on_change, widget);
+ if (change_spec) {
+ var ajax = {
+ url: '/web/dataset/call',
+ async: false
+ };
+ return self.rpc(ajax, {
+ model: self.dataset.model,
+ method: change_spec.method,
+ args: [(self.datarecord.id == null ? [] : [self.datarecord.id])].concat(change_spec.args),
+ context_id: change_spec.context_index == undefined ? null : change_spec.context_index + 1
+ }).pipe(function(response) {
+ return self.on_processed_onchange(response, processed);
+ });
+ } else {
+ console.warn("Wrong on_change format", on_change);
+ }
}
- }
} catch(e) {
console.error(e);
return $.Deferred().reject();
diff --git a/addons/web/static/test/onchange.js b/addons/web/static/test/onchange.js
new file mode 100644
index 00000000000..9f047f33d93
--- /dev/null
+++ b/addons/web/static/test/onchange.js
@@ -0,0 +1,65 @@
+$(document).ready(function () {
+ var openerp,
+ make_form = function (default_values) {
+ var fields = {};
+ _(default_values).each(function (value, name) {
+ fields[name] = value instanceof Function ? value : {
+ get_on_change_value: function () { return value; }
+ };
+ });
+ return _.extend(new openerp.web.FormView(null, {}),
+ {fields: fields});
+ };
+ module("form.onchange", {
+ setup: function () {
+ openerp = window.openerp.init(true);
+ window.openerp.web.core(openerp);
+ window.openerp.web.chrome(openerp);
+ // views loader stuff
+ window.openerp.web.data(openerp);
+ window.openerp.web.views(openerp);
+ window.openerp.web.list(openerp);
+ window.openerp.web.form(openerp);
+ }
+ });
+ test('Parse args-less onchange', function () {
+ var f = new openerp.web.FormView(null, {});
+ var result = f.parse_on_change('on_change_foo()', {});
+ equal(result.method, 'on_change_foo');
+ deepEqual(result.args, []);
+ });
+ test('Parse 1-arg onchange', function () {
+ var f = make_form({foo: 3});
+ var result = f.parse_on_change('on_change_foo(foo)', {});
+ equal(result.method, 'on_change_foo');
+ deepEqual(result.args, [3]);
+ });
+ test('Parse 2-args onchange', function () {
+ var f = make_form({foo: 3, bar: 'qux'});
+ var result = f.parse_on_change('on_change_foo(bar, foo)', {});
+ equal(result.method, 'on_change_foo');
+ deepEqual(result.args, ['qux', 3]);
+ });
+ test('Literal null', function () {
+ var f = make_form();
+ var result = f.parse_on_change('on_null(None)', {});
+ deepEqual(result.args, [null]);
+ });
+ test('Literal true', function () {
+ var f = make_form();
+ var result = f.parse_on_change('on_null(True)', {});
+ deepEqual(result.args, [true]);
+ });
+ test('Literal false', function () {
+ var f = make_form();
+ var result = f.parse_on_change('on_null(False)', {});
+ deepEqual(result.args, [false]);
+ });
+ test('Literal string', function () {
+ var f = make_form();
+ var result = f.parse_on_change('on_str("foo")', {});
+ deepEqual(result.args, ['foo']);
+ var result2 = f.parse_on_change("on_str('foo')", {});
+ deepEqual(result2.args, ['foo']);
+ });
+});
diff --git a/addons/web/static/test/test.html b/addons/web/static/test/test.html
index d182ce18707..9bbfff168fd 100644
--- a/addons/web/static/test/test.html
+++ b/addons/web/static/test/test.html
@@ -49,4 +49,5 @@
+