import {vlFormValidation} from '/src/vl-form-validation.js';
/**
* Gebruik de form validation element mixin in combinatie met elementen die formulier validatie bevatten.
* @mixin vlFormValidationElement
*
* @param {Object} SuperClass - Class die als base class gebruikt zal worden.
* @return {Object} class
*/
export const vlFormValidationElement = (SuperClass) => {
return class extends SuperClass {
static get formAssociated() {
return true;
}
constructor(html) {
super(html);
if (this.attachInternals && customElements.get(this.localName)) {
this._internals = this.attachInternals();
}
}
disconnectedCallback() {
if (this._observer) {
this._observer.disconnect();
}
}
/**
* Sets a custom validity message for the element.
*
* @param {string} message
*/
setCustomValidity(message) {
if (this._inputElement) {
this._inputElement.setCustomValidity(message);
} else if (this._internals) {
if (message) {
this._internals.setValidity({customError: true}, message);
} else {
this._internals.setValidity({});
}
} else if (super.setCustomValidity) {
super.setCustomValidity(message);
}
}
/**
* Returns true if the element's child controls are subject to constraint validation and satisfy those contraints; returns false if some controls do not satisfy their constraints. Fires an event named invalid at any control that does not satisfy its constraints; such controls are considered invalid if the event is not canceled. It is up to the programmer to decide how to respond to false.
*
* @return {boolean}
*/
checkValidity() {
if (this._inputElement) {
return this._inputElement.checkValidity();
} else if (this._internals) {
return this._internals.checkValidity();
} else if (super.checkValidity) {
return super.checkValidity();
} else {
return true;
}
}
_dressFormValidation() {
if (this.form && this.form.hasAttribute('data-vl-validate')) {
this._setClassAttributes();
this._observer = this._observeFormValidationClasses();
Object.assign(this, vlFormValidation);
this.dress(this.form);
this.addEventListener('focus', () => this.focus());
}
}
get _inputElement() {
if (this.shadowRoot) {
return this.shadowRoot.querySelector('input');
}
}
_observeFormValidationClasses() {
const observer = new MutationObserver((mutations) => {
['error', 'success'].forEach((type) => {
if (mutations.find((mutation) => [...mutation.target.classList].find((clazz) => clazz.includes(this.getAttribute(`data-vl-${type}-class`))))) {
if (!this.hasAttribute(`data-vl-${type}`)) {
this.setAttribute(`data-vl-${type}`, '');
}
} else {
this.removeAttribute(`data-vl-${type}`);
}
});
});
observer.observe(this, {attributes: true, attributeFilter: ['class']});
return observer;
}
_nameChangedCallback(oldValue, newValue) {
if (this._inputElement && this._inputElement.name != newValue) {
this._inputElement.name = newValue;
this.setAttribute('name', newValue);
}
}
_requiredChangedCallback(oldValue, newValue) {
const attributes = ['data-required', 'required', 'aria-required'];
if (newValue == undefined) {
attributes.forEach((attribute) => {
this.removeAttribute(attribute);
if (this._inputElement) {
this._inputElement.removeAttribute(attribute);
}
});
} else if (newValue != undefined && oldValue == undefined) {
attributes.forEach((attribute) => {
const value = attribute === 'required' ? '' : 'true';
this.setAttribute(attribute, value);
if (this._inputElement) {
this._inputElement.setAttribute(attribute, value);
}
});
}
}
_dataRequiredChangedCallback(oldValue, newValue) {
this._requiredChangedCallback(oldValue, newValue);
}
_errorPlaceholderChangedCallback(oldValue, newValue) {
this.setAttribute('aria-describedby', newValue);
}
_setClassAttributes() {
this.setAttribute('data-vl-success-class', `vl-input-field--success`);
this.setAttribute('data-vl-error-class', `vl-input-field--error`);
}
};
};