fix select to use selected options

This commit is contained in:
Konnor Rogers
2025-06-19 23:39:07 -04:00
parent d20945d78b
commit c4e08c09bd
3 changed files with 82 additions and 21 deletions

View File

@@ -6,6 +6,53 @@ native: select
icon: select
---
```html {.example}
<form id="base-example">
<wa-select name="select-1" value="option-2">
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
<wa-option value="option-4">Option 4</wa-option>
<wa-option value="option-5">Option 5</wa-option>
<wa-option value="option-6">Option 6</wa-option>
</wa-select>
<br>
<wa-select name="select-2" multiple value="option-4">
<wa-option value="option-1">Option 1</wa-option>
<wa-option value="option-2">Option 2</wa-option>
<wa-option value="option-3">Option 3</wa-option>
<wa-option value="option-4">Option 4</wa-option>
<wa-option value="option-5">Option 5</wa-option>
<wa-option value="option-6">Option 6</wa-option>
</wa-select>
<br>
<wa-button type="reset">Reset</wa-button>
</form>
<br>
<pre><code id="formdata"></code></pre>
<script type="module">
const form = document.querySelector("#base-example")
function showFormData() {
const code = document.querySelector("#formdata")
const formdata = new FormData(form)
const obj = {}
for (const key of formdata.keys()) {
obj[key] = formdata.getAll(key).length > 1 ? formdata.getAll(key) : formdata.get(key)
}
code.innerHTML = JSON.stringify(obj, null, 2)
}
form.addEventListener("change", (e) => {
showFormData()
})
await customElements.whenDefined("wa-select")
await customElements.whenDefined("wa-option")
setTimeout(() => {
showFormData()
})
</script>
```
```html {.example}
<wa-select>
<wa-option value="option-1">Option 1</wa-option>
@@ -400,4 +447,3 @@ This can be hard to conceptualize, so heres a fairly large example showing how l
container.addEventListener("submit", handleLazySubmit)
</script>
```

View File

@@ -46,8 +46,6 @@ export default class WaOption extends WebAwesomeElement {
// Set via the parent select
@state() current = false;
@state() selected = false;
/**
* The option's value. When selected, the containing form control will receive this value. The value must be unique
* from other options in the same group. Values may not contain spaces, as spaces are used as delimiters when listing
@@ -56,7 +54,11 @@ export default class WaOption extends WebAwesomeElement {
@property({ reflect: true }) value = '';
/** Draws the option in a disabled state, preventing selection. */
@property({ type: Boolean, reflect: true }) disabled = false;
@property({ type: Boolean }) disabled = false;
@property({ type: Boolean, attribute: false }) selected = false
@property({ type: Boolean, attribute: "selected" }) defaultSelected = false
_label: string = '';
/**
@@ -136,6 +138,17 @@ export default class WaOption extends WebAwesomeElement {
}
};
protected willUpdate(changedProperties: PropertyValues<this>): void {
if (changedProperties.has('defaultSelected')) {
if (!this.closest("wa-select")?.hasInteracted) {
const oldVal = this.selected
this.selected = this.defaultSelected
this.requestUpdate("selected", oldVal)
}
}
super.willUpdate(changedProperties)
}
updated(changedProperties: PropertyValues<this>) {
super.updated(changedProperties);
@@ -146,6 +159,7 @@ export default class WaOption extends WebAwesomeElement {
if (changedProperties.has('selected')) {
this.setAttribute('aria-selected', this.selected ? 'true' : 'false');
this.customStates.set('selected', this.selected);
this.closest("wa-select")?.selectionChanged?.()
}
if (changedProperties.has('value')) {
@@ -155,12 +169,6 @@ export default class WaOption extends WebAwesomeElement {
this.value = String(this.value);
}
if (this.value.includes(' ')) {
// eslint-disable-next-line no-console
console.error(`Option values cannot include a space. All spaces have been replaced with underscores.`, this);
this.value = this.value.replace(/ /g, '_');
}
this.handleDefaultSlotChange();
}

View File

@@ -127,12 +127,7 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement {
private _defaultValue: string | string[] = '';
@property({
attribute: 'value',
reflect: true,
converter: {
fromAttribute: (value: string) => value.split(' '),
toAttribute: (value: string | string[]) => (Array.isArray(value) ? value.join(' ') : value),
},
attribute: false,
})
set defaultValue(val: string | string[]) {
this._defaultValue = this.convertDefaultValue(val);
@@ -154,29 +149,33 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement {
const isMultiple = this.multiple || this.hasAttribute('multiple');
if (!isMultiple && Array.isArray(val)) {
val = val.join(' ');
val = val[0];
}
return val;
}
private _value: string[] | undefined;
@property({ attribute: false })
@property({ attribute: "value", reflect: false })
set value(val: string | string[]) {
let oldValue = this.value;
if ((val as any) instanceof FormData) {
val = (val as unknown as FormData).getAll(this.name) as string[]
}
if (!Array.isArray(val)) {
val = val.split(' ');
}
if (!this._value || this._value.join(' ') !== val.join(' ')) {
// if (!this._value || this._value.join(' ') !== val.join(' ')) {
this._value = val;
let newValue = this.value;
if (newValue !== oldValue) {
this.requestUpdate('value', oldValue);
}
}
// }
}
get value() {
@@ -645,7 +644,10 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement {
const newSelectedOptions = Array.isArray(option) ? option : [option];
// Clear existing selection
allOptions.forEach(el => (el.selected = false));
allOptions.forEach(el => {
if (newSelectedOptions.includes(el)) { return }
el.selected = false
});
// Set the new selection
if (newSelectedOptions.length) {
@@ -847,6 +849,11 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement {
this.value = this.defaultValue;
super.formResetCallback();
this.handleValueChange();
this.updateComplete.then(() => {
this.dispatchEvent(new InputEvent('input', { bubbles: true, composed: true }));
this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
})
}
render() {