Skip to content

Commit

Permalink
fix(select): check state with disabled option
Browse files Browse the repository at this point in the history
  • Loading branch information
ogunb committed Dec 14, 2023
1 parent 41e69a6 commit 2359b67
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/components/select/bl-select.css
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ legend span {
padding: var(--bl-size-xs) 0;
background: var(--background-color);
z-index: 1;
font: var(--bl-font-title-3-regular);

/* Make sure option focus doesn't overflow */
box-shadow: 10px 0 0 var(--background-color), -10px 0 0 var(--background-color);
Expand Down
29 changes: 29 additions & 0 deletions src/components/select/bl-select.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { sendKeys } from "@web/test-runner-commands";
import BlSelect from "./bl-select";
import BlButton from "../button/bl-button";
import BlCheckbox from "../checkbox-group/checkbox/bl-checkbox";
import "../checkbox-group/checkbox/bl-checkbox";
import type BlSelectOption from "./option/bl-select-option";

describe("bl-select", () => {
Expand Down Expand Up @@ -595,5 +596,33 @@ describe("bl-select", () => {
expect(selectAll.indeterminate).to.be.true;
expect(selectAll.checked).to.be.false;
});

it('should uncheck "select all" checkbox when all available options are selected', async () => {
const el = await fixture<BlSelect>(html`<bl-select multiple>
<bl-select-option value="1" disabled>Option 1</bl-select-option>
<bl-select-option value="2" selected>Option 2</bl-select-option>
<bl-select-option value="3" selected>Option 3</bl-select-option>
<bl-select-option value="4" selected>Option 4</bl-select-option>
<bl-select-option value="5" selected>Option 5</bl-select-option>
</bl-select>`);

const selectAll = el.shadowRoot!.querySelector<BlCheckbox>(".select-all")!;

expect(selectAll.indeterminate).to.be.true;
expect(selectAll.checked).to.be.false;

setTimeout(() => selectAll.dispatchEvent(
new CustomEvent("bl-checkbox-change", { detail: true }))
);

const event = await oneEvent(el, "bl-select");

expect(event).to.exist;
expect(event.detail.length).to.equal(0);
expect(el.selectedOptions.length).to.equal(0);

expect(selectAll.indeterminate).to.be.false;
expect(selectAll.checked).to.be.false;
});
});
});
49 changes: 35 additions & 14 deletions src/components/select/bl-select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { FormControlMixin, requiredValidator } from "@open-wc/form-control";
import { FormValue } from "@open-wc/form-helpers";
import "element-internals-polyfill";
import { event, EventDispatcher } from "../../utilities/event";
import BlCheckbox from "../checkbox-group/checkbox/bl-checkbox";
import "../icon/bl-icon";
import style from "../select/bl-select.css";
import "../select/option/bl-select-option";
Expand Down Expand Up @@ -289,20 +290,6 @@ export default class BlSelect<ValueType extends FormValue = string> extends Form
});
}

private _handleSelectAll(e: CustomEvent) {
const checked = e.detail;

this._connectedOptions.forEach(option => {
if (option.disabled) {
return;
}

option.selected = checked;
});

this._handleMultipleSelect();
}

connectedCallback(): void {
super.connectedCallback();

Expand Down Expand Up @@ -490,6 +477,40 @@ export default class BlSelect<ValueType extends FormValue = string> extends Form
}
}

private _handleSelectAll(e: CustomEvent) {
const selectAllEl = this.shadowRoot?.querySelector(".select-all") as BlCheckbox;

const checked = e.detail;
const unselectedOptions = this._connectedOptions.filter(option => !option.selected);
const isAllUnselectedDisabled = unselectedOptions.every(option => option.disabled);

// If all available options are selected, instead of checking, uncheck all options
if (checked && isAllUnselectedDisabled) {
setTimeout(() => {
const checkbox = selectAllEl?.shadowRoot?.querySelector("input");

checkbox?.click();
}, 0);
return;
}

this._connectedOptions.forEach(option => {
if (option.disabled) {
return;
}

option.selected = checked;
});

this._handleMultipleSelect();

// Make sure the checkbox state is in sync with selected options
setTimeout(() => {
selectAllEl.checked = this.isAllSelected;
selectAllEl.indeterminate = this._selectedOptions.length > 0 && !this.isAllSelected;
});
}

private _onClickRemove(e: MouseEvent) {
e.stopPropagation();

Expand Down

0 comments on commit 2359b67

Please sign in to comment.