Use synchronous calls for on_change's and Field.set
Those calls can be triggered by event like focus-out. So to ensure a correct order of the flow, we must defer the processing of the result. issue8482 review273571002
This commit is contained in:
1 parent
65b553c660
commit
12b60612ea
4 files changed
+176
-224
No files matched your search
+160
-201
@@ -115,10 +115,9 @@
|
||||
record._changed.id = true;
|
||||
});
|
||||
var root_group = this.root_group;
|
||||
this.changed().then(function() {
|
||||
root_group.screens.forEach(function(screen) {
|
||||
screen.display();
|
||||
});
|
||||
this.changed();
|
||||
root_group.screens.forEach(function(screen) {
|
||||
screen.display();
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -233,17 +232,9 @@
|
||||
}));
|
||||
}
|
||||
this.parent._changed[this.child_name] = true;
|
||||
var changed_prm = this.parent.model.fields[this.child_name]
|
||||
.changed(this.parent);
|
||||
// One2Many.changed could return undefined
|
||||
if (!changed_prm) {
|
||||
changed_prm = jQuery.when();
|
||||
}
|
||||
return changed_prm.then(function() {
|
||||
this.parent.validate(null, true).done(function() {
|
||||
return this.parent.group.changed();
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
this.parent.model.fields[this.child_name].changed(this.parent);
|
||||
this.parent.validate(null, true, false, true);
|
||||
this.parent.group.changed();
|
||||
};
|
||||
array.delete_ = function(records) {
|
||||
if (jQuery.isEmptyObject(records)) {
|
||||
@@ -742,7 +733,6 @@
|
||||
validate = true;
|
||||
}
|
||||
var name, value;
|
||||
var promises = [];
|
||||
var rec_named_fields = ['many2one', 'one2one', 'reference'];
|
||||
var later = {};
|
||||
var fieldnames = [];
|
||||
@@ -772,22 +762,18 @@
|
||||
var related = name + '.';
|
||||
this._values[related] = values[related] || {};
|
||||
}
|
||||
promises.push(this.model.fields[name].set(this, value));
|
||||
this.model.fields[name].set(this, value);
|
||||
this._loaded[name] = true;
|
||||
fieldnames.push(name);
|
||||
}
|
||||
for (name in later) {
|
||||
value = later[name];
|
||||
promises.push(this.model.fields[name].set(this, value));
|
||||
this.model.fields[name].set(this, value);
|
||||
this._loaded[name] = true;
|
||||
}
|
||||
if (validate) {
|
||||
this.validate(fieldnames, true, false, false);
|
||||
}
|
||||
return jQuery.when.apply(jQuery, promises.filter(Boolean))
|
||||
.then(function() {
|
||||
for (var i = 0; i < fieldnames.length; i++) {
|
||||
this._loaded[fieldnames[i]] = true;
|
||||
}
|
||||
if (validate) {
|
||||
return this.validate(fieldnames, true);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
get: function() {
|
||||
var value = {};
|
||||
@@ -897,24 +883,22 @@
|
||||
fieldnames.push(fname);
|
||||
}
|
||||
return jQuery.when.apply(jQuery, promises).then(function() {
|
||||
return this.on_change(fieldnames).then(function() {
|
||||
return this.on_change_with(fieldnames).then(function() {
|
||||
var callback = function() {
|
||||
if (display) {
|
||||
return this.group.root_group.screens
|
||||
.forEach(function(screen) {
|
||||
return screen.display();
|
||||
});
|
||||
}
|
||||
}.bind(this);
|
||||
if (validate) {
|
||||
return this.validate(null, true)
|
||||
.then(callback);
|
||||
} else {
|
||||
return callback();
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
this.on_change(fieldnames);
|
||||
this.on_change_with(fieldnames);
|
||||
var callback = function() {
|
||||
if (display) {
|
||||
return this.group.root_group.screens
|
||||
.forEach(function(screen) {
|
||||
return screen.display();
|
||||
});
|
||||
}
|
||||
}.bind(this);
|
||||
if (validate) {
|
||||
return this.validate(null, true)
|
||||
.then(callback);
|
||||
} else {
|
||||
return callback();
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
get_timestamp: function() {
|
||||
@@ -982,23 +966,22 @@
|
||||
}
|
||||
}.bind(this));
|
||||
if (!jQuery.isEmptyObject(values)) {
|
||||
var prm;
|
||||
if (fieldnames.length == 1) {
|
||||
prm = this.model.execute(
|
||||
'on_change_' + fieldnames[0],
|
||||
[values], this.get_context())
|
||||
.then(this.set_on_change.bind(this));
|
||||
} else {
|
||||
prm = this.model.execute('on_change',
|
||||
[values, fieldnames], this.get_context())
|
||||
.then(function(changes) {
|
||||
return jQuery.when.apply(jQuery,
|
||||
changes.map(this.set_on_change.bind(this)));
|
||||
}.bind(this));
|
||||
var changes;
|
||||
try {
|
||||
if (fieldnames.length == 1) {
|
||||
changes = [];
|
||||
changes.push(this.model.execute(
|
||||
'on_change_' + fieldnames[0],
|
||||
[values], this.get_context(), false));
|
||||
} else {
|
||||
changes = this.model.execute(
|
||||
'on_change',
|
||||
[values, fieldnames], this.get_context(), false);
|
||||
}
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
return prm;
|
||||
} else {
|
||||
return jQuery.when();
|
||||
changes.forEach(this.set_on_change, this);
|
||||
}
|
||||
},
|
||||
on_change_with: function(field_names) {
|
||||
@@ -1039,48 +1022,43 @@
|
||||
delete this._values[fieldname + '.'];
|
||||
}
|
||||
}
|
||||
var prms = [];
|
||||
var prm;
|
||||
var set_on_change = function(fieldname) {
|
||||
return function(result) {
|
||||
return this.model.fields[fieldname].set_on_change(
|
||||
this, result);
|
||||
};
|
||||
};
|
||||
var result;
|
||||
fieldnames = Object.keys(fieldnames);
|
||||
if (fieldnames) {
|
||||
if (fieldnames.length == 1) {
|
||||
prm = this.model.execute(
|
||||
'on_change_with_' + fieldnames[0],
|
||||
[values], this.get_context());
|
||||
prms.push(prm.then(set_on_change(fieldnames[0]).bind(this)));
|
||||
} else {
|
||||
prm = this.model.execute(
|
||||
'on_change_with',
|
||||
[values, fieldnames], this.get_context());
|
||||
prms.push(prm.then(this.set_on_change.bind(this)));
|
||||
try {
|
||||
if (fieldnames.length == 1) {
|
||||
fieldname = fieldnames[0];
|
||||
result = {};
|
||||
result[fieldname] = this.model.execute(
|
||||
'on_change_with_' + fieldname,
|
||||
[values], this.get_context(), false);
|
||||
} else {
|
||||
result = this.model.execute(
|
||||
'on_change_with',
|
||||
[values, fieldnames], this.get_context(), false);
|
||||
}
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
this.set_on_change(result);
|
||||
}
|
||||
for (fieldname in later) {
|
||||
if (!later.hasOwnProperty(fieldname)) {
|
||||
continue;
|
||||
}
|
||||
on_change_with = this.model.fields[fieldname]
|
||||
.description.on_change_with;
|
||||
values = this._get_on_change_args(on_change_with);
|
||||
prm = this.model.execute('on_change_with_' + fieldname,
|
||||
[values], this.get_context());
|
||||
prms.push(prm.then(set_on_change(fieldname).bind(this)));
|
||||
try {
|
||||
result = this.model.execute(
|
||||
'on_change_with_' + fieldname,
|
||||
[values], this.get_context(), false);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
this.model.fields[fieldname].set_on_change(this, result);
|
||||
}
|
||||
return jQuery.when.apply(jQuery, prms);
|
||||
},
|
||||
set_on_change: function(values) {
|
||||
var fieldname, value;
|
||||
var promises = [];
|
||||
for (fieldname in values) {
|
||||
if (!values.hasOwnProperty(fieldname)) {
|
||||
continue;
|
||||
}
|
||||
value = values[fieldname];
|
||||
if (!(fieldname in this.model.fields)) {
|
||||
continue;
|
||||
@@ -1092,46 +1070,41 @@
|
||||
var related = fieldname + '.';
|
||||
this._values[related] = values[related] || {};
|
||||
}
|
||||
promises.push(
|
||||
this.model.fields[fieldname].set_on_change(this, value));
|
||||
this.model.fields[fieldname].set_on_change(this, value);
|
||||
}
|
||||
return jQuery.when.apply(jQuery, promises);
|
||||
},
|
||||
autocomplete_with: function(fieldname) {
|
||||
var promises = [];
|
||||
for (var fname in this.model.fields) {
|
||||
var field = this.model.fields[fname];
|
||||
var autocomplete = field.description.autocomplete || [];
|
||||
if (!~autocomplete.indexOf(fieldname)) {
|
||||
continue;
|
||||
}
|
||||
promises.push(this.do_autocomplete(fname));
|
||||
this.do_autocomplete(fname);
|
||||
}
|
||||
return jQuery.when.apply(jQuery, promises);
|
||||
},
|
||||
do_autocomplete: function(fieldname) {
|
||||
this.autocompletion[fieldname] = [];
|
||||
var field = this.model.fields[fieldname];
|
||||
var autocomplete = field.description.autocomplete;
|
||||
var values = this._get_on_change_args(autocomplete);
|
||||
var prm = this.model.execute(
|
||||
'autocomplete_' + fieldname, [values], this.get_context());
|
||||
return prm.then(function(result) {
|
||||
this.autocompletion[fieldname] = result;
|
||||
}.bind(this));
|
||||
var result;
|
||||
try {
|
||||
result = this.model.execute(
|
||||
'autocomplete_' + fieldname, [values], this.get_context(),
|
||||
false);
|
||||
} catch (e) {
|
||||
result = [];
|
||||
}
|
||||
this.autocompletion[fieldname] = result;
|
||||
},
|
||||
reset: function(value) {
|
||||
this.cancel();
|
||||
return this.set(value, true).then(function() {
|
||||
var promises = [];
|
||||
if (this.group.parent) {
|
||||
promises.push(this.group.parent.on_change(
|
||||
[this.group.child_name]));
|
||||
promises.push(this.group.parent.on_change_with(
|
||||
[this.group.child_name]));
|
||||
}
|
||||
return jQuery.when.apply(jQuery, promises);
|
||||
}.bind(this));
|
||||
this.set(value, true);
|
||||
if (this.group.parent) {
|
||||
this.group.parent.on_change([this.group.child_name]);
|
||||
this.group.parent.on_change_with([this.group.child_name]);
|
||||
}
|
||||
},
|
||||
expr_eval: function(expr) {
|
||||
if (typeof(expr) != 'string') return expr;
|
||||
@@ -1396,20 +1369,16 @@
|
||||
if (JSON.stringify(previous_value) !=
|
||||
JSON.stringify(this.get(record))) {
|
||||
record._changed[this.name] = true;
|
||||
this.changed(record).done(function() {
|
||||
record.validate(null, true).then(function() {
|
||||
record.group.changed();
|
||||
});
|
||||
});
|
||||
this.changed(record);
|
||||
record.validate(null, true, false, true);
|
||||
record.group.changed();
|
||||
} else if (force_change) {
|
||||
record._changed[this.name] = true;
|
||||
this.changed(record).done(function() {
|
||||
record.validate(null, true).then(function() {
|
||||
var root_group = record.group.root_group;
|
||||
root_group.screens.forEach(function(screen) {
|
||||
screen.display();
|
||||
});
|
||||
});
|
||||
this.changed(record);
|
||||
record.validate(null, true, false, true);
|
||||
var root_group = record.group.root_group;
|
||||
root_group.screens.forEach(function(screen) {
|
||||
screen.display();
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -1425,13 +1394,10 @@
|
||||
record._changed[this.name] = true;
|
||||
},
|
||||
changed: function(record) {
|
||||
return record.on_change([this.name]).then(function() {
|
||||
return record.on_change_with([this.name]).then(function() {
|
||||
return record.autocomplete_with(this.name).then(function() {
|
||||
record.set_field_context();
|
||||
});
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
record.on_change([this.name]);
|
||||
record.on_change_with([this.name]);
|
||||
record.autocomplete_with(this.name);
|
||||
record.set_field_context();
|
||||
},
|
||||
get_timestamp: function(record) {
|
||||
return {};
|
||||
@@ -1959,39 +1925,35 @@
|
||||
'.fields_get',
|
||||
'params': [Object.keys(field_names), context]
|
||||
};
|
||||
prm = Sao.rpc(args, record.model.session);
|
||||
}
|
||||
}
|
||||
var set_value = function(fields) {
|
||||
var promises = [];
|
||||
if (!jQuery.isEmptyObject(fields)) {
|
||||
try {
|
||||
fields = Sao.rpc(args, record.model.session, false);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
group.add_fields(fields);
|
||||
}
|
||||
if (mode == 'list ids') {
|
||||
for (var i = 0, len = group.length; i < len; i++) {
|
||||
var old_record = group[i];
|
||||
if (!~value.indexOf(old_record.id)) {
|
||||
group.remove(old_record, true);
|
||||
}
|
||||
}
|
||||
if (mode == 'list ids') {
|
||||
for (var i = 0, len = group.length; i < len; i++) {
|
||||
var old_record = group[i];
|
||||
if (!~value.indexOf(old_record.id)) {
|
||||
group.remove(old_record, true);
|
||||
}
|
||||
group.load(value, modified);
|
||||
} else {
|
||||
value.forEach(function(vals) {
|
||||
var new_record = group.new_(false);
|
||||
if (default_) {
|
||||
// Don't validate as parent will validate
|
||||
promises.push(new_record.set_default(
|
||||
vals, false, false));
|
||||
group.add(new_record, -1, false);
|
||||
} else {
|
||||
promises.push(new_record.set(vals));
|
||||
group.push(new_record);
|
||||
}
|
||||
});
|
||||
}
|
||||
return jQuery.when.apply(jQuery, promises);
|
||||
};
|
||||
return prm.then(set_value.bind(this));
|
||||
group.load(value, modified);
|
||||
} else {
|
||||
value.forEach(function(vals) {
|
||||
var new_record = group.new_(false);
|
||||
if (default_) {
|
||||
// Don't validate as parent will validate
|
||||
new_record.set_default(vals, false, false);
|
||||
group.add(new_record, -1, false);
|
||||
} else {
|
||||
new_record.set(vals);
|
||||
group.push(new_record);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
set: function(record, value, _default) {
|
||||
if (_default === undefined) {
|
||||
@@ -2009,7 +1971,7 @@
|
||||
}
|
||||
record._values[this.name] = undefined;
|
||||
this._set_default_value(record, model);
|
||||
return this._set_value(record, value, _default);
|
||||
this._set_value(record, value, _default);
|
||||
},
|
||||
get: function(record) {
|
||||
var group = record._values[this.name];
|
||||
@@ -2083,20 +2045,16 @@
|
||||
this._set_value(record, value, false, modified);
|
||||
if (modified) {
|
||||
record._changed[this.name] = true;
|
||||
this.changed(record).done(function() {
|
||||
record.validate(null, true).then(function() {
|
||||
record.group.changed();
|
||||
});
|
||||
});
|
||||
this.changed(record);
|
||||
record.validate(null, true, false, true);
|
||||
record.group.changed();
|
||||
} else if (force_change) {
|
||||
record._changed[this.name] = true;
|
||||
this.changed(record).done(function() {
|
||||
record.validate(null, true).then(function() {
|
||||
var root_group = record.group.root_group;
|
||||
root_group.screens.forEach(function(screen) {
|
||||
screen.display();
|
||||
});
|
||||
});
|
||||
this.changed(record);
|
||||
record.validate(null, true, false, true);
|
||||
var root_group = record.group.root_group;
|
||||
root_group.screens.forEach(function(screen) {
|
||||
screen.display();
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -2109,15 +2067,15 @@
|
||||
return this.set(record, value, true);
|
||||
},
|
||||
set_on_change: function(record, value) {
|
||||
var fields;
|
||||
record._changed[this.name] = true;
|
||||
this._set_default_value(record);
|
||||
if (value instanceof Array) {
|
||||
return this._set_value(record, value, false, true);
|
||||
}
|
||||
var prm = jQuery.when();
|
||||
if (value.add || value.update) {
|
||||
var context = this.get_context(record);
|
||||
var fields = record._values[this.name].model.fields;
|
||||
fields = record._values[this.name].model.fields;
|
||||
var field_names = {};
|
||||
var adding_values = [];
|
||||
if (value.add) {
|
||||
@@ -2144,7 +2102,13 @@
|
||||
'.fields_get',
|
||||
'params': [Object.keys(field_names), context]
|
||||
};
|
||||
prm = Sao.rpc(args, record.model.session);
|
||||
try {
|
||||
fields = Sao.rpc(args, record.model.session, false);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
fields = {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2168,33 +2132,28 @@
|
||||
}.bind(this));
|
||||
|
||||
if (value.add || value.update) {
|
||||
prm = prm.then(function(fields) {
|
||||
var promises = [];
|
||||
group.add_fields(fields);
|
||||
if (value.add) {
|
||||
value.add.forEach(function(vals) {
|
||||
var index = vals[0];
|
||||
var data = vals[1];
|
||||
var new_record = group.new_(false);
|
||||
group.add(new_record, index, false);
|
||||
promises.push(new_record.set_on_change(data));
|
||||
});
|
||||
}
|
||||
if (value.update) {
|
||||
value.update.forEach(function(vals) {
|
||||
if (!vals.id) {
|
||||
return;
|
||||
}
|
||||
var record2 = group.get(vals.id);
|
||||
if (record2) {
|
||||
promises.push(record2.set_on_change(vals));
|
||||
}
|
||||
});
|
||||
}
|
||||
return jQuery.when.apply(jQuery, promises);
|
||||
}.bind(this));
|
||||
group.add_fields(fields);
|
||||
if (value.add) {
|
||||
value.add.forEach(function(vals) {
|
||||
var index = vals[0];
|
||||
var data = vals[1];
|
||||
var new_record = group.new_(false);
|
||||
group.add(new_record, index, false);
|
||||
new_record.set_on_change(data);
|
||||
});
|
||||
}
|
||||
if (value.update) {
|
||||
value.update.forEach(function(vals) {
|
||||
if (!vals.id) {
|
||||
return;
|
||||
}
|
||||
var record2 = group.get(vals.id);
|
||||
if (record2) {
|
||||
record2.set_on_change(vals);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return prm;
|
||||
},
|
||||
_set_default_value: function(record, model) {
|
||||
if (record._values[this.name] !== undefined) {
|
||||
|
||||
+3
-7
@@ -1365,15 +1365,11 @@
|
||||
return prm.then(function() {
|
||||
group.add(record, this.new_model_position());
|
||||
this.current_record = record;
|
||||
var prm = jQuery.when();
|
||||
if (previous_view.view_type == 'calendar') {
|
||||
prm = previous_view.set_default_date(
|
||||
record, selected_date);
|
||||
previous_view.set_default_date(record, selected_date);
|
||||
}
|
||||
prm.then(function() {
|
||||
this.display().done(function() {
|
||||
this.set_cursor(true, true);
|
||||
}.bind(this));
|
||||
this.display().done(function() {
|
||||
this.set_cursor(true, true);
|
||||
}.bind(this));
|
||||
return record;
|
||||
}.bind(this));
|
||||
|
||||
@@ -306,9 +306,8 @@
|
||||
selected_date = Sao.Date(selected_date);
|
||||
}
|
||||
field.set(record, selected_date);
|
||||
return record.on_change([dtstart]).then(function() {
|
||||
return record.on_change_with([dtstart]);
|
||||
});
|
||||
record.on_change([dtstart]);
|
||||
record.on_change_with([dtstart]);
|
||||
},
|
||||
get_selected_date: function(){
|
||||
return this.el.fullCalendar('getDate');
|
||||
|
||||
+11
-13
@@ -1301,22 +1301,20 @@ function eval_pyson(value){
|
||||
var record = this.record;
|
||||
if (this.datalist) {
|
||||
this.datalist.empty();
|
||||
var set_autocompletion = function() {
|
||||
var selection = [];
|
||||
if (record) {
|
||||
selection = record.autocompletion[this.field_name] || [];
|
||||
var selection;
|
||||
if (record) {
|
||||
if (!(this.field_name in record.autocompletion)) {
|
||||
record.do_autocomplete(this.field_name);
|
||||
}
|
||||
selection.forEach(function(e) {
|
||||
jQuery('<option/>', {
|
||||
'value': e
|
||||
}).appendTo(this.datalist);
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
if (record && !(this.field_name in record.autocompletion)) {
|
||||
record.do_autocomplete(this.field_name).done(set_autocompletion);
|
||||
selection = record.autocompletion[this.field_name] || [];
|
||||
} else {
|
||||
set_autocompletion();
|
||||
selection = [];
|
||||
}
|
||||
selection.forEach(function(e) {
|
||||
jQuery('<option/>', {
|
||||
'value': e
|
||||
}).appendTo(this.datalist);
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
// Set size
|
||||
|
||||
Reference in new issue
Block a user