lion/packages/checkbox-group/src/LionCheckboxGroup.js

88 lines
2.9 KiB
JavaScript

import { LionFieldset } from '@lion/fieldset';
export class LionCheckboxGroup extends LionFieldset {
constructor() {
super();
this._checkboxGroupTouched = false;
this._setTouchedAndPrefilled = this._setTouchedAndPrefilled.bind(this);
this._checkForOutsideClick = this._checkForOutsideClick.bind(this);
this._checkForChildrenClick = this._checkForChildrenClick.bind(this);
}
connectedCallback() {
super.connectedCallback();
// We listen for focusin(instead of foxus), because it bubbles and gives the right event order
window.addEventListener('focusin', this._setTouchedAndPrefilled);
document.addEventListener('click', this._checkForOutsideClick);
this.addEventListener('click', this._checkForChildrenClick);
// checks for any of the children to be prefilled
this._checkboxGroupPrefilled = super.prefilled;
}
disconnectedCallback() {
super.disconnectedCallback();
window.removeEventListener('focusin', this._setTouchedAndPrefilled);
document.removeEventListener('click', this._checkForOutsideClick);
this.removeEventListener('click', this._checkForChildrenClick);
}
get touched() {
return this._checkboxGroupTouched;
}
/**
* Leave event will be fired when previous document.activeElement
* is inside group and current document.activeElement is outside.
*/
_setTouchedAndPrefilled() {
const groupHasFocus = this.focused;
if (this.__groupHadFocus && !groupHasFocus) {
this._checkboxGroupTouched = true;
this._checkboxGroupPrefilled = super.prefilled; // right time to reconsider prefilled
this.__checkboxGroupPrefilledHasBeenSet = true;
}
this.__groupHadFocus = groupHasFocus;
}
_checkForOutsideClick(event) {
const outsideGroupClicked = !this.contains(event.target);
if (outsideGroupClicked) {
this._setTouchedAndPrefilled();
}
}
// Whenever a user clicks a checkbox, error messages should become visible
_checkForChildrenClick(event) {
const childClicked = this._childArray.some(c => c === event.target || c.contains(event.target));
if (childClicked) {
this._checkboxGroupTouched = true;
}
}
get _childArray() {
// We assume here that the fieldset has one set of checkboxes/radios that are grouped via attr
// name="groupName[]"
const arrayKey = Object.keys(this.formElements).filter(k => k.substr(-2) === '[]')[0];
return this.formElements[arrayKey] || [];
}
// eslint-disable-next-line class-methods-use-this
__isRequired(modelValues) {
const keys = Object.keys(modelValues);
for (let i = 0; i < keys.length; i += 1) {
const modelValue = modelValues[keys[i]];
if (Array.isArray(modelValue)) {
// grouped via myName[]
return {
required: modelValue.some(node => node.checked),
};
}
return {
required: modelValue.checked,
};
}
return { required: false };
}
}