[FIX] web: display empty input fields properly

Before this commit, it was not possible to see the difference between an
unset float field (with a 'false' value) and a set field (for ex, with
value 0)

This was due to the fact that the formatFloat/formatMonetary functions
format false values as the number 0, unlike many other formatting
functions.
This commit is contained in:
Géry Debongnie
2017-05-08 13:56:18 +02:00
parent aeae2fb64f
commit c8d77f93e5
5 changed files with 71 additions and 17 deletions
@@ -93,9 +93,6 @@ var DebouncedField = AbstractField.extend({
// _debouncedStarted is used to detect that the user interacted at least
// once with the widget, so that we can prevent it from triggering a
// field_changed in commitChanges if the user didn't change anything
// (this is required as sometimes it is hard to detect that an unset
// value is still unset, e.g. if a numerical field contains the value 0,
// is it because it is still unset or because the user set it to 0?
this._debouncedStarted = false;
if (this.mode === 'edit') {
if (this.DEBOUNCE) {
+10 -4
View File
@@ -71,7 +71,7 @@ function formatChar(value) {
* @returns {string}
*/
function formatDate(value, field, options) {
if (!value) {
if (value === false) {
return "";
}
if (!options || !('timezone' in options) || options.timezone) {
@@ -96,7 +96,7 @@ function formatDate(value, field, options) {
* @returns {string}
*/
function formatDateTime(value, field, options) {
if (!value) {
if (value === false) {
return "";
}
if (!options || !('timezone' in options) || options.timezone) {
@@ -113,7 +113,7 @@ function formatDateTime(value, field, options) {
* Returns a string representing a float. The result takes into account the
* user settings (to display the correct decimal separator).
*
* @param {float} value the value that should be formatted
* @param {float|false} value the value that should be formatted
* @param {Object} [field] a description of the field (returned by fields_get
* for example). It may contain a description of the number of digits that
* should be used.
@@ -124,6 +124,9 @@ function formatDateTime(value, field, options) {
* @returns {string}
*/
function formatFloat(value, field, options) {
if (value === false) {
return "";
}
var l10n = core._t.database.parameters;
var precision;
if (options && options.digits) {
@@ -213,7 +216,7 @@ function formatX2Many(value) {
* Returns a string representing a monetary value. The result takes into account
* the user settings (to display the correct decimal separator, currency, ...).
*
* @param {float} value the value that should be formatted
* @param {float|false} value the value that should be formatted
* @param {Object} [field]
* a description of the field (returned by fields_get for example). It
* may contain a description of the number of digits that should be used.
@@ -238,6 +241,9 @@ function formatX2Many(value) {
* @returns {string}
*/
function formatMonetary(value, field, options) {
if (value === false) {
return "";
}
options = options || {};
var currency = options.currency;
@@ -415,9 +415,9 @@ QUnit.module('basic_fields', {
'</tree>',
});
var zeroValues = list.$('td').filter(function () {return $(this).text() === '0.000';});
assert.strictEqual(zeroValues.length, 2,
'Unset float values should be rendered as zeros.');
var zeroValues = list.$('td.o_data_cell').filter(function () {return $(this).text() === '';});
assert.strictEqual(zeroValues.length, 1,
'Unset float values should be rendered as empty strings.');
// switch to edit mode
var $cell = list.$('tr.o_data_row td:not(.o_list_record_selector)').first();
@@ -441,8 +441,8 @@ QUnit.module('basic_fields', {
QUnit.test('do not trigger a field_changed if they have not changed', function (assert) {
assert.expect(2);
this.data.partner.records[1].qux = undefined;
this.data.partner.records[1].int_field = undefined;
this.data.partner.records[1].qux = false;
this.data.partner.records[1].int_field = false;
var form = createView({
View: FormView,
model: 'partner',
@@ -1659,9 +1659,9 @@ QUnit.module('basic_fields', {
assert.strictEqual(euroValues.length, 1,
'One one line has euro as a currency.');
var zeroValues = list.$('td').filter(function () {return _.str.include($(this).text(), '0.00');});
assert.strictEqual(zeroValues.length, 2,
'Unset float values should be rendered as zeros.');
var zeroValues = list.$('td.o_data_cell').filter(function () {return $(this).text() === '';});
assert.strictEqual(zeroValues.length, 1,
'Unset float values should be rendered as empty strings.');
// switch to edit mode
var $cell = list.$('tr.o_data_row td:not(.o_list_record_selector):contains($)');
@@ -23,13 +23,13 @@ QUnit.test('format integer', function(assert) {
assert.strictEqual(fieldUtils.format.integer(106500), '106,50,0');
assert.strictEqual(fieldUtils.format.integer(0), "0");
assert.strictEqual(fieldUtils.format.integer(undefined), "");
assert.strictEqual(fieldUtils.format.integer(false), "");
core._t.database.parameters.grouping = originalGrouping;
});
QUnit.test('format float', function(assert) {
assert.expect(4);
assert.expect(5);
var originalParameters = $.extend(true, {}, core._t.database.parameters);
@@ -48,6 +48,7 @@ QUnit.test('format float', function(assert) {
thousands_sep: '.'
});
assert.strictEqual(fieldUtils.format.float(6000), '6.000,00');
assert.strictEqual(fieldUtils.format.float(false), '');
core._t.database.parameters = originalParameters;
});
@@ -70,6 +71,12 @@ QUnit.test("format_many2one", function (assert) {
}));
});
QUnit.test('format monetary', function(assert) {
assert.expect(1);
assert.strictEqual(fieldUtils.format.monetary(false), '');
});
QUnit.test('format char', function(assert) {
assert.expect(1);
@@ -696,6 +696,50 @@ QUnit.module('Views', {
form.destroy();
});
QUnit.test('required float fields works as expected', function (assert) {
assert.expect(8);
this.data.partner.fields.qux.required = true;
var form = createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form string="Partners">' +
'<sheet>' +
'<group>' +
'<field name="qux"/>' +
'</group>' +
'</sheet>' +
'</form>',
mockRPC: function (route, args) {
assert.step(args.method);
return this._super.apply(this, arguments);
},
});
assert.ok(form.$('input[name="qux"]').hasClass('o_required_modifier'),
"qux input is flagged as required");
assert.strictEqual(form.$('input[name="qux"]').val(), "",
"qux input is empty");
form.$buttons.find('.o_form_button_save').click();
assert.ok(form.$('input[name="qux"]').hasClass('o_field_invalid'),
"qux input is displayed as invalid");
form.$('input[name="qux"]').val("0").trigger('input');
form.$buttons.find('.o_form_button_save').click();
form.$buttons.find('.o_form_button_edit').click();
assert.strictEqual(form.$('input[name="qux"]').val(), "0.0",
"qux input is properly formatted");
assert.verifySteps(['default_get', 'create', 'read']);
form.destroy();
});
QUnit.test('separators', function (assert) {
assert.expect(1);