Skip to content
Merged
25 changes: 22 additions & 3 deletions packages/webawesome/src/components/option/option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,13 @@ export default class WaOption extends WebAwesomeElement {
if (changedProperties.has('defaultSelected')) {
// We cast to <wa-select> because it shares the same API as combobox
if (!this.closest<WaSelect>('wa-combobox, wa-select')?.hasInteracted) {
const oldVal = this.selected;
this.selected = this.defaultSelected;
this.requestUpdate('selected', oldVal);
// Only sync if defaultSelected is becoming true
// This prevents overwriting `selected` when it was set directly by frameworks like Vue
if (this.defaultSelected) {
const oldVal = this.selected;
this.selected = this.defaultSelected;
this.requestUpdate('selected', oldVal);
}
}
}
super.willUpdate(changedProperties);
Expand Down Expand Up @@ -183,6 +187,21 @@ export default class WaOption extends WebAwesomeElement {
}
}

protected firstUpdated(changedProperties: PropertyValues<this>) {
super.firstUpdated(changedProperties);

// If the `selected` property was set directly (e.g., by Vue's :selected binding),
// notify the parent select to update its selection. This is needed because
// Vue binds to the `selected` property instead of the `defaultSelected` property
// when using `:selected="true"` syntax.
if (this.selected && !this.defaultSelected) {
const parent = this.closest<WaSelect>('wa-select, wa-combobox');
if (parent && !parent.hasInteracted) {
parent.selectionChanged?.();
}
}
}
Comment on lines +190 to +203
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 I'm a little worried about this firing many times for initial page load as selectionChanged() is going to iterate all <wa-option> elements everytime a new one is added and could make this fire many times, and to me seems like an expensive operation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any suggestions to move this forward?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd feel safer with something like a debounced selectionChanged tbh, but thats just my personal preference.

This is probably fine tbh


private updateDefaultLabel() {
let oldValue = this.defaultLabel;
this.defaultLabel = getText(this).trim();
Expand Down
41 changes: 41 additions & 0 deletions packages/webawesome/src/components/select/select.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,47 @@ describe('<wa-select>', () => {
const values = formData.getAll('test');
expect(values).to.have.members(['option with spaces', 'another option']);
});

it('should select options using the selected attribute with with-clear', async () => {
// Issue #1922: selected attribute was ignored when with-clear was present
const el = await fixture<WaSelect>(html`
<wa-select with-clear>
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2" selected>Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
</wa-select>
`);

expect(el.value).to.equal('option-2');
expect(el.displayInput.value).to.equal('Option 2');
});

it('should select options with selected attribute, with-clear, and placeholder', async () => {
// This is the exact combination reported in bug #1922
const el = await fixture<WaSelect>(html`
<wa-select placeholder="Placeholder" with-clear>
<wa-option value="option-1" selected>Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
</wa-select>
`);

expect(el.value).to.equal('option-1');
expect(el.displayInput.value).to.equal('Option 1');
});

it('should select multiple options with selected attribute and with-clear', async () => {
const el = await fixture<WaSelect>(html`
<wa-select multiple with-clear>
<wa-option value="option-1" selected>Option 1</wa-option>
<wa-option value="option-2" selected>Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
</wa-select>
`);

expect(el.value).to.have.members(['option-1', 'option-2']);
expect(el.value).to.have.length(2);
});
});

it('should allow interaction after being disabled and re-enabled', async () => {
Expand Down
1 change: 0 additions & 1 deletion packages/webawesome/src/components/select/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement {
private selectionOrder: Map<string, number> = new Map();
private typeToSelectString = '';
private typeToSelectTimeout: number;

@query('.select') popup: WaPopup;
@query('.combobox') combobox: HTMLSlotElement;
@query('.display-input') displayInput: HTMLInputElement;
Expand Down