fix(checkbox-group): indeterminate checkbox respects disabled states (#1698)
Co-authored-by: Danny Moerkerke <danny.moerkerke@ing.com>
This commit is contained in:
parent
6c0b0201e6
commit
05e17d69e5
4 changed files with 145 additions and 7 deletions
5
.changeset/mighty-bats-decide.md
Normal file
5
.changeset/mighty-bats-decide.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@lion/checkbox-group': patch
|
||||
---
|
||||
|
||||
Checkbox indeterminate now properly handles disabled states on child checkboxes.
|
||||
|
|
@ -13,7 +13,6 @@ export class LionCheckboxIndeterminate extends LionCheckbox {
|
|||
:host .choice-field__nested-checkboxes {
|
||||
display: block;
|
||||
}
|
||||
|
||||
::slotted([slot='checkbox']) {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
|
@ -86,6 +85,7 @@ export class LionCheckboxIndeterminate extends LionCheckbox {
|
|||
|
||||
this.__settingOwnChecked = true;
|
||||
const checkedElements = subCheckboxes.filter(checkbox => checkbox.checked);
|
||||
|
||||
switch (subCheckboxes.length - checkedElements.length) {
|
||||
// all checked
|
||||
case 0:
|
||||
|
|
@ -147,16 +147,32 @@ export class LionCheckboxIndeterminate extends LionCheckbox {
|
|||
}
|
||||
|
||||
this.__settingOwnSubs = true;
|
||||
if (this.indeterminate && this.mixedState) {
|
||||
|
||||
const subCheckboxes = this._subCheckboxes;
|
||||
const checkedElements = subCheckboxes.filter(checkbox => checkbox.checked);
|
||||
const disabledElements = subCheckboxes.filter(checkbox => checkbox.disabled);
|
||||
const allChecked =
|
||||
subCheckboxes.length > 0 && subCheckboxes.length === checkedElements.length;
|
||||
const allDisabled =
|
||||
subCheckboxes.length > 0 && subCheckboxes.length === disabledElements.length;
|
||||
const hasDisabledElements = disabledElements.length > 0;
|
||||
|
||||
if (allDisabled) {
|
||||
this.checked = allChecked;
|
||||
}
|
||||
|
||||
if (this.indeterminate && (this.mixedState || hasDisabledElements)) {
|
||||
this._subCheckboxes.forEach((checkbox, i) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
checkbox.checked = this._indeterminateSubStates[i];
|
||||
});
|
||||
} else {
|
||||
this._subCheckboxes.forEach(checkbox => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
checkbox.checked = this._inputNode.checked;
|
||||
});
|
||||
this._subCheckboxes
|
||||
.filter(checkbox => !checkbox.disabled)
|
||||
.forEach(checkbox => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
checkbox.checked = this._inputNode.checked;
|
||||
});
|
||||
}
|
||||
this.updateComplete.then(() => {
|
||||
this.__settingOwnSubs = false;
|
||||
|
|
|
|||
|
|
@ -153,6 +153,34 @@ describe('<lion-checkbox-indeterminate>', () => {
|
|||
expect(elIndeterminate?.checked).to.be.true;
|
||||
});
|
||||
|
||||
it('should become indeterminate if all children except disabled ones are checked', async () => {
|
||||
// Arrange
|
||||
const el = /** @type {LionCheckboxGroup} */ (
|
||||
await fixture(html`
|
||||
<lion-checkbox-group name="scientists[]">
|
||||
<lion-checkbox-indeterminate label="Favorite scientists">
|
||||
<lion-checkbox slot="checkbox" label="Archimedes"></lion-checkbox>
|
||||
<lion-checkbox slot="checkbox" label="Francis Bacon" disabled></lion-checkbox>
|
||||
<lion-checkbox slot="checkbox" label="Marie Curie"></lion-checkbox>
|
||||
</lion-checkbox-indeterminate>
|
||||
</lion-checkbox-group>
|
||||
`)
|
||||
);
|
||||
const elIndeterminate = /** @type {LionCheckboxIndeterminate} */ (
|
||||
el.querySelector('lion-checkbox-indeterminate')
|
||||
);
|
||||
const { _subCheckboxes } = getCheckboxIndeterminateMembers(elIndeterminate);
|
||||
|
||||
// Act
|
||||
_subCheckboxes[0].checked = true;
|
||||
_subCheckboxes[2].checked = true;
|
||||
await el.updateComplete;
|
||||
|
||||
// Assert
|
||||
expect(elIndeterminate?.hasAttribute('indeterminate')).to.be.true;
|
||||
expect(elIndeterminate?.checked).to.be.false;
|
||||
});
|
||||
|
||||
it('should sync all children when parent is checked (from indeterminate to checked)', async () => {
|
||||
// Arrange
|
||||
const el = /** @type {LionCheckboxGroup} */ (
|
||||
|
|
@ -182,6 +210,95 @@ describe('<lion-checkbox-indeterminate>', () => {
|
|||
expect(_subCheckboxes[2].hasAttribute('checked')).to.be.true;
|
||||
});
|
||||
|
||||
it('should not sync any disabled children when parent is checked (from indeterminate to checked)', async () => {
|
||||
// Arrange
|
||||
const el = /** @type {LionCheckboxGroup} */ (
|
||||
await fixture(html`
|
||||
<lion-checkbox-group name="scientists[]">
|
||||
<lion-checkbox-indeterminate label="Favorite scientists">
|
||||
<lion-checkbox slot="checkbox" label="Archimedes"></lion-checkbox>
|
||||
<lion-checkbox slot="checkbox" label="Francis Bacon" disabled></lion-checkbox>
|
||||
<lion-checkbox slot="checkbox" label="Marie Curie"></lion-checkbox>
|
||||
</lion-checkbox-indeterminate>
|
||||
</lion-checkbox-group>
|
||||
`)
|
||||
);
|
||||
const elIndeterminate = /** @type {LionCheckboxIndeterminate} */ (
|
||||
el.querySelector('lion-checkbox-indeterminate')
|
||||
);
|
||||
const { _subCheckboxes, _inputNode } = getCheckboxIndeterminateMembers(elIndeterminate);
|
||||
|
||||
// Act
|
||||
_inputNode.click();
|
||||
await elIndeterminate.updateComplete;
|
||||
|
||||
// Assert
|
||||
expect(elIndeterminate.hasAttribute('indeterminate')).to.be.true;
|
||||
expect(_subCheckboxes[0].hasAttribute('checked')).to.be.true;
|
||||
expect(_subCheckboxes[1].hasAttribute('checked')).to.be.false;
|
||||
expect(_subCheckboxes[2].hasAttribute('checked')).to.be.true;
|
||||
});
|
||||
|
||||
it('should remain unchecked when parent is clicked and all children are disabled', async () => {
|
||||
// Arrange
|
||||
const el = /** @type {LionCheckboxGroup} */ (
|
||||
await fixture(html`
|
||||
<lion-checkbox-group name="scientists[]">
|
||||
<lion-checkbox-indeterminate label="Favorite scientists">
|
||||
<lion-checkbox slot="checkbox" label="Archimedes" disabled></lion-checkbox>
|
||||
<lion-checkbox slot="checkbox" label="Francis Bacon" disabled></lion-checkbox>
|
||||
<lion-checkbox slot="checkbox" label="Marie Curie" disabled></lion-checkbox>
|
||||
</lion-checkbox-indeterminate>
|
||||
</lion-checkbox-group>
|
||||
`)
|
||||
);
|
||||
const elIndeterminate = /** @type {LionCheckboxIndeterminate} */ (
|
||||
el.querySelector('lion-checkbox-indeterminate')
|
||||
);
|
||||
const { _subCheckboxes, _inputNode } = getCheckboxIndeterminateMembers(elIndeterminate);
|
||||
|
||||
// Act
|
||||
_inputNode.click();
|
||||
await elIndeterminate.updateComplete;
|
||||
|
||||
// Assert
|
||||
expect(elIndeterminate.hasAttribute('indeterminate')).to.be.false;
|
||||
expect(elIndeterminate.hasAttribute('checked')).to.be.false;
|
||||
expect(_subCheckboxes[0].hasAttribute('checked')).to.be.false;
|
||||
expect(_subCheckboxes[1].hasAttribute('checked')).to.be.false;
|
||||
expect(_subCheckboxes[2].hasAttribute('checked')).to.be.false;
|
||||
});
|
||||
|
||||
it('should remain checked when parent is clicked and all children are disabled and checked', async () => {
|
||||
// Arrange
|
||||
const el = /** @type {LionCheckboxGroup} */ (
|
||||
await fixture(html`
|
||||
<lion-checkbox-group name="scientists[]">
|
||||
<lion-checkbox-indeterminate label="Favorite scientists">
|
||||
<lion-checkbox slot="checkbox" label="Archimedes" disabled checked></lion-checkbox>
|
||||
<lion-checkbox slot="checkbox" label="Francis Bacon" disabled checked></lion-checkbox>
|
||||
<lion-checkbox slot="checkbox" label="Marie Curie" disabled checked></lion-checkbox>
|
||||
</lion-checkbox-indeterminate>
|
||||
</lion-checkbox-group>
|
||||
`)
|
||||
);
|
||||
const elIndeterminate = /** @type {LionCheckboxIndeterminate} */ (
|
||||
el.querySelector('lion-checkbox-indeterminate')
|
||||
);
|
||||
const { _subCheckboxes, _inputNode } = getCheckboxIndeterminateMembers(elIndeterminate);
|
||||
|
||||
// Act
|
||||
_inputNode.click();
|
||||
await elIndeterminate.updateComplete;
|
||||
|
||||
// Assert
|
||||
expect(elIndeterminate.hasAttribute('indeterminate')).to.be.false;
|
||||
expect(elIndeterminate.hasAttribute('checked')).to.be.true;
|
||||
expect(_subCheckboxes[0].hasAttribute('checked')).to.be.true;
|
||||
expect(_subCheckboxes[1].hasAttribute('checked')).to.be.true;
|
||||
expect(_subCheckboxes[2].hasAttribute('checked')).to.be.true;
|
||||
});
|
||||
|
||||
it('should sync all children when parent is checked (from unchecked to checked)', async () => {
|
||||
// Arrange
|
||||
const el = /** @type {LionCheckboxGroup} */ (
|
||||
|
|
|
|||
|
|
@ -3430,7 +3430,7 @@ autosize@4.0.2:
|
|||
resolved "https://registry.yarnpkg.com/autosize/-/autosize-4.0.2.tgz#073cfd07c8bf45da4b9fd153437f5bafbba1e4c9"
|
||||
integrity sha512-jnSyH2d+qdfPGpWlcuhGiHmqBJ6g3X+8T+iRwFrHPLVcdoGJE/x6Qicm6aDHfTsbgZKxyV8UU/YB2p4cjKDRRA==
|
||||
|
||||
awesome-phonenumber@3.0.1:
|
||||
awesome-phonenumber@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/awesome-phonenumber/-/awesome-phonenumber-3.0.1.tgz#8d73aaa1c2b0a660b117567b0d9797623457e1d0"
|
||||
integrity sha512-H5rqjTJ1+HxmyuSKDoPgvHUgP+RBRhtWQ25ccy4BmSLQL5UVg3K+yo2QCX4IlkxiVNst3suGMArV9TH7B1KEPw==
|
||||
|
|
|
|||
Loading…
Reference in a new issue