summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorAaron Bohy <aab@odoo.com>2017-06-29 11:46:46 +0200
committerAaron Bohy <aab@odoo.com>2017-06-29 14:58:04 +0200
commit8473bde80e6609d552af8b00396c72a20bd3c47f (patch)
treee31d77429533eb4199ca2a8a49df9588c82e01b6 /addons/web/static/src
parentb954cd64835eb2c251ba0890293079b7bcebd460 (diff)
[FIX] web: handle 'domain' key returned by onchanges
Onchange RPCs return an object that may contain a 'domain' key. When it does, its value is an object whose keys are field names and values are the new domain for the corresponding field. Before this rev., the 'domain' key was totally ignored by the BasicModel. This feature is used for example in the account.payment form view (go to an open invoice, click on 'Register payment'): the domain of field payment_method_id is updated by the onchanges (e.g. when changing the journal_id). As the domain was ignored, it always displayed all possible payment methods.
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/fields/relational_fields.js104
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js10
-rw-r--r--addons/web/static/src/xml/base.xml14
3 files changed, 88 insertions, 40 deletions
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js
index 44f884f130c..df7f018369d 100644
--- a/addons/web/static/src/js/fields/relational_fields.js
+++ b/addons/web/static/src/js/fields/relational_fields.js
@@ -1785,15 +1785,7 @@ var FieldSelection = AbstractField.extend({
*/
init: function () {
this._super.apply(this, arguments);
- if (this.field.type === 'many2one') {
- this.values = this.record.specialData[this.name];
- this.formatType = 'many2one';
- } else {
- this.values = _.reject(this.field.selection, function (v) {
- return v[0] === false && v[1] === '';
- });
- }
- this.values = [[false, this.attrs.placeholder || '']].concat(this.values);
+ this._setValues();
},
//--------------------------------------------------------------------------
@@ -1823,13 +1815,12 @@ var FieldSelection = AbstractField.extend({
* @private
*/
_renderEdit: function () {
- if (!this.$el.children().length) {
- for (var i = 0 ; i < this.values.length ; i++) {
- this.$el.append($('<option/>', {
- value: JSON.stringify(this.values[i][0]),
- html: this.values[i][1]
- }));
- }
+ this.$el.empty();
+ for (var i = 0 ; i < this.values.length ; i++) {
+ this.$el.append($('<option/>', {
+ value: JSON.stringify(this.values[i][0]),
+ html: this.values[i][1]
+ }));
}
var value = this.value;
if (this.field.type === 'many2one' && value) {
@@ -1844,6 +1835,31 @@ var FieldSelection = AbstractField.extend({
_renderReadonly: function () {
this.$el.empty().text(this._formatValue(this.value));
},
+ /**
+ * @override
+ */
+ _reset: function () {
+ this._super.apply(this, arguments);
+ this._setValues();
+ },
+ /**
+ * Sets the possible field values. If the field is a many2one, those values
+ * may change during the lifecycle of the widget if the domain change (an
+ * onchange may change the domain).
+ *
+ * @private
+ */
+ _setValues: function () {
+ if (this.field.type === 'many2one') {
+ this.values = this.record.specialData[this.name];
+ this.formatType = 'many2one';
+ } else {
+ this.values = _.reject(this.field.selection, function (v) {
+ return v[0] === false && v[1] === '';
+ });
+ }
+ this.values = [[false, this.attrs.placeholder || '']].concat(this.values);
+ },
//--------------------------------------------------------------------------
// Handlers
@@ -1869,7 +1885,9 @@ var FieldSelection = AbstractField.extend({
});
var FieldRadio = FieldSelection.extend({
- template: 'FieldRadio',
+ template: null,
+ className: 'o_field_radio',
+ tagName: 'span',
specialData: "_fetchSpecialMany2ones",
supportedFieldTypes: ['selection', 'many2one'],
events: _.extend({}, AbstractField.prototype.events, {
@@ -1880,14 +1898,12 @@ var FieldRadio = FieldSelection.extend({
*/
init: function () {
this._super.apply(this, arguments);
- if (this.field.type === 'selection') {
- this.values = this.field.selection || [];
- } else if (this.field.type === 'many2one') {
- this.values = _.map(this.record.specialData[this.name], function (val) {
- return [val.id, val.display_name];
- });
+ if (this.mode === 'edit') {
+ this.tagName = 'div';
+ this.className += this.nodeOptions.horizontal ? 'o_horizontal' : 'o_vertical';
}
this.unique_id = _.uniqueId("radio");
+ this._setValues();
},
//--------------------------------------------------------------------------
@@ -1911,17 +1927,45 @@ var FieldRadio = FieldSelection.extend({
* @override
*/
_renderEdit: function () {
- var value;
+ var self = this;
+ var currentValue;
if (this.field.type === 'many2one') {
- value = this.value && this.value.data.id;
+ currentValue = this.value && this.value.data.id;
} else {
- value = this.value;
+ currentValue = this.value;
}
- var index = _.findIndex(this.values, function (option) {
- return option[0] === value;
+ this.$el.empty();
+ _.each(this.values, function (value, index) {
+ self.$el.append(qweb.render('FieldRadio.button', {
+ checked: value[0] === currentValue,
+ id: self.unique_id + '_' + value[0],
+ index: index,
+ value: value,
+ }));
});
- this.$("input").prop("checked", false);
- this.$('input[data-index="' + index + '"]').prop('checked', true);
+ },
+ /**
+ * @override
+ */
+ _reset: function () {
+ this._super.apply(this, arguments);
+ this._setValues();
+ },
+ /**
+ * Sets the possible field values. If the field is a many2one, those values
+ * may change during the lifecycle of the widget if the domain change (an
+ * onchange may change the domain).
+ *
+ * @private
+ */
+ _setValues: function () {
+ if (this.field.type === 'selection') {
+ this.values = this.field.selection || [];
+ } else if (this.field.type === 'many2one') {
+ this.values = _.map(this.record.specialData[this.name], function (val) {
+ return [val.id, val.display_name];
+ });
+ }
},
//--------------------------------------------------------------------------
diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js
index 69c6c13f9a7..01b2a18091a 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -1791,7 +1791,9 @@ var BasicModel = AbstractModel.extend({
var context = record.getContext({fieldName: fieldName});
var domain = record.getDomain({fieldName: fieldName});
if (domain.length) {
- var localID = record._changes && record._changes[fieldName] || record.data[fieldName];
+ var localID = (record._changes && fieldName in record._changes) ?
+ record._changes[fieldName] :
+ record.data[fieldName];
if (localID) {
var element = this.localData[localID];
domain = ["|", ["id", "=", element.data.id]].concat(domain);
@@ -2994,6 +2996,12 @@ var BasicModel = AbstractModel.extend({
});
record._warning = true;
}
+ if (result.domain) {
+ var fieldsInfo = record.fieldsInfo[viewType || record.viewType];
+ for (var fieldName in result.domain) {
+ fieldsInfo[fieldName].domain = result.domain[fieldName];
+ }
+ }
return self._applyOnChange(result.value, record).then(function () {
return result;
});
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index bcc832c822c..06e6b8b2285 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -724,15 +724,11 @@
t-att-autofocus="widget.attrs.autofocus"
t-att-id="widget.idForLabel"/>
</t>
-<t t-name="FieldRadio">
- <span t-if="widget.mode === 'readonly'"/>
-
- <div t-if="widget.mode !== 'readonly'" t-attf-class="o_field_radio #{widget.nodeOptions.horizontal ? 'o_horizontal' : 'o_vertical'}">
- <div t-foreach="widget.values" t-as="value" class="o_radio_item">
- <input type="radio" class="o_radio_input" t-att-id="widget.unique_id + '_' + value[0]"
- t-att-name="widget.unique_id" t-att-data-value="value[0]" t-att-data-index="value_index"/>
- <label t-if="!widget.nodeOptions.no_radiolabel" class="o_form_label" t-att-for="widget.unique_id + '_' + value[0]"><t t-esc="value[1]"/></label>
- </div>
+<t t-name="FieldRadio.button">
+ <div class="o_radio_item">
+ <input type="radio" class="o_radio_input" t-att-checked="checked ? true : undefined"
+ t-att-data-value="value[0]" t-att-data-index="index" t-att-id="id"/>
+ <label class="o_form_label" t-att-for="id"><t t-esc="value[1]"/></label>
</div>
</t>
<t t-name="FieldMany2One">