diff --git a/src/vaadin-combo-box-mixin.html b/src/vaadin-combo-box-mixin.html
index ad30324f..26b4586b 100644
--- a/src/vaadin-combo-box-mixin.html
+++ b/src/vaadin-combo-box-mixin.html
@@ -1093,6 +1093,27 @@
this._clear();
}
+ /**
+ * @param {boolean} invalid
+ * @protected
+ */
+ _setInvalid(invalid) {
+ if (this._shouldSetInvalid(invalid)) {
+ this.invalid = invalid;
+ }
+ }
+
+ /**
+ * Override this method to define whether the given `invalid` state should be set.
+ *
+ * @param {boolean} _invalid
+ * @return {boolean}
+ * @protected
+ */
+ _shouldSetInvalid(_invalid) {
+ return true;
+ }
+
/**
* Validates the field and sets the `invalid` property based on the result.
*
@@ -1102,7 +1123,7 @@
*/
validate() {
const isValid = this.checkValidity();
- this.invalid = !isValid;
+ this._setInvalid(!isValid);
this.dispatchEvent(new CustomEvent('validated', {detail: {valid: isValid}}));
return isValid;
}
diff --git a/test/validation.html b/test/validation.html
index 1affc7c5..6cbd9bfa 100644
--- a/test/validation.html
+++ b/test/validation.html
@@ -82,6 +82,24 @@
expect(event.detail.valid).to.be.false;
});
});
+ describe('invalid cannot be set to false', () => {
+ let comboBox;
+
+ beforeEach(async() => {
+ comboBox = fixture('combo-box');
+ comboBox._shouldSetInvalid = (invalid) => invalid;
+ await nextRender();
+ });
+
+ it('should set invalid only when it is true', async() => {
+ comboBox.required = true;
+ comboBox.validate();
+ expect(comboBox.invalid).to.be.true;
+ comboBox.value = 'foo';
+ comboBox.validate();
+ expect(comboBox.invalid).to.be.true;
+ });
+ });