diff --git a/addons/web/static/src/legacy/js/fields/basic_fields.js b/addons/web/static/src/legacy/js/fields/basic_fields.js index 3d4df0cb0a1..179d2771686 100644 --- a/addons/web/static/src/legacy/js/fields/basic_fields.js +++ b/addons/web/static/src/legacy/js/fields/basic_fields.js @@ -695,6 +695,31 @@ var FieldDateRange = InputField.extend({ } this._super.apply(this, arguments); }, + + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Field widget is valid if value entered can convered to date/dateime value + * while parsing input value to date/datetime throws error then widget considered + * invalid + * + * @override + */ + isValid: function () { + const value = this.mode === "readonly" ? this.value : this.$input.val(); + try { + return field_utils.parse[this.formatType](value, this.field, { timezone: true }) || true; + } catch (error) { + return false; + } + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + /** * Return the date written in the input, in UTC. * @@ -702,7 +727,14 @@ var FieldDateRange = InputField.extend({ * @returns {Moment|false} */ _getValue: function () { - return field_utils.parse[this.formatType](this.$input.val(), this.field, { timezone: true }); + try { + // user may enter manual value in input and it may not be parsed as date/datetime value + this.removeInvalidClass(); + return field_utils.parse[this.formatType](this.$input.val(), this.field, { timezone: true }); + } catch (error) { + this.setInvalidClass(); + return false; + } }, //-------------------------------------------------------------------------- diff --git a/addons/web/static/tests/legacy/fields/basic_fields_tests.js b/addons/web/static/tests/legacy/fields/basic_fields_tests.js index fa7ed263804..aaf227863b5 100644 --- a/addons/web/static/tests/legacy/fields/basic_fields_tests.js +++ b/addons/web/static/tests/legacy/fields/basic_fields_tests.js @@ -3852,6 +3852,49 @@ QUnit.module('basic_fields', { form.destroy(); }); + QUnit.test('Daterange field manually input wrong value should show toaster', async function (assert) { + assert.expect(5); + + this.data.partner.fields.date_end = { string: 'Date End', type: 'date' }; + this.data.partner.records[0].date_end = '2017-02-08'; + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: ` +
+ + + `, + interceptsPropagate: { + call_service: function (ev) { + if (ev.data.service === 'notification') { + assert.strictEqual(ev.data.method, 'notify'); + assert.strictEqual(ev.data.args[0].title, 'Invalid fields:'); + assert.strictEqual(ev.data.args[0].message, '
  • A date
'); + } + } + }, + }); + + await testUtils.fields.editInput(form.$('.o_field_date_range:first'), 'blabla'); + // click outside daterange field + await testUtils.dom.click(form.$el); + assert.hasClass(form.$('input[name=date]'), 'o_field_invalid', + "date field should be displayed as invalid"); + // update input date with right value + await testUtils.fields.editInput(form.$('.o_field_date_range:first'), '02/08/2017'); + assert.doesNotHaveClass(form.$('input[name=date]'), 'o_field_invalid', + "date field should not be displayed as invalid now"); + + // again enter wrong value and try to save should raise invalid fields value + await testUtils.fields.editInput(form.$('.o_field_date_range:first'), 'blabla'); + await testUtils.form.clickSave(form); + + form.destroy(); + }); + QUnit.module('FieldDate'); QUnit.test('date field: toggle datepicker [REQUIRE FOCUS]', async function (assert) {