Skip to content

plugin/bound: reapply the select value when its options change - #77

Merged
rameel merged 1 commit into
mainfrom
bound/select-options
Oct 25, 2026
Merged

rameel merged 1 commit into
mainfrom
bound/select-options

Conversation

@rameel

@rameel rameel commented Oct 25, 2026

Copy link
Copy Markdown
Owner

x-bound applied the bound value to a <select> when the value changed, and once when its deferred binding started, after x-for had rendered the initial options. Options that changed after that were not synced: when x-for items were loaded from an empty list, added, or changed their values, the select showed the first option while the property kept its value. Options inside an <optgroup> and <select multiple> were affected the same way.

Observe the options and apply the bound value again whenever they change: options added or removed anywhere in the select, their value attributes, and their text. Alpine fixed the same case for x-model in 3.16.0 (alpinejs/alpine#4769), observing only the select's direct children.

The deferred start stays. When the property is null or undefined, it is initialized from the element, and before Alpine initializes the options that value is wrong: with <option :value="0">None</option> the property would get "None" instead of 0.

x-bound applied the bound value to a <select> when the value changed,
and once when its deferred binding started, after x-for had rendered
the initial options. Options that changed after that were not synced:
when x-for items were loaded from an empty list, added, or changed
their values, the select showed the first option while the property
kept its value. Options inside an <optgroup> and <select multiple>
were affected the same way.

Observe the options and apply the bound value again whenever they
change. The deferred start stays: when the property is null or
undefined, it is initialized from the element, and before Alpine
initializes the options that value is wrong, e.g. an option with
:value="0" would give its text instead of 0.
@github-actions

Copy link
Copy Markdown

📦 Bundle size comparison

Name Size Gzip Brotli Δ
alpinegear-bound.esm.min.js 4.10 KiB (+146 B) 1.88 KiB (+69 B) 1.63 KiB (+64 B) 🔴
alpinegear-bound.min.js 4.14 KiB (+146 B) 1.90 KiB (+72 B) 1.65 KiB (+65 B) 🔴
alpinegear-destroy.esm.min.js 128 B 123 B 91 B
alpinegear-destroy.min.js 191 B 167 B 123 B
alpinegear-dialog.esm.min.js 1.75 KiB 951 B 811 B
alpinegear-dialog.min.js 1.79 KiB 967 B 822 B
alpinegear-format.esm.min.js 1.18 KiB 645 B 579 B
alpinegear-format.min.js 1.25 KiB 680 B 587 B
alpinegear-fragment.esm.min.js 1.51 KiB 785 B 667 B
alpinegear-fragment.min.js 1.57 KiB 817 B 700 B
alpinegear-hotkey.esm.min.js 1.97 KiB 1.08 KiB 964 B
alpinegear-hotkey.min.js 2.03 KiB 1.10 KiB 996 B
alpinegear-main.esm.min.js 7.91 KiB (+146 B) 3.22 KiB (+49 B) 2.84 KiB (+49 B) 🔴
alpinegear-main.min.js 7.87 KiB (+146 B) 3.17 KiB (+55 B) 2.79 KiB (+50 B) 🔴
alpinegear-markdown.esm.min.js 19.27 KiB 7.26 KiB 6.61 KiB
alpinegear-markdown.min.js 19.32 KiB 7.27 KiB 6.63 KiB
alpinegear-match.esm.min.js 1.98 KiB 1004 B 868 B
alpinegear-match.min.js 2.05 KiB 1.01 KiB 897 B
alpinegear-router.esm.min.js 9.48 KiB 4.06 KiB 3.62 KiB
alpinegear-router.min.js 9.53 KiB 4.08 KiB 3.65 KiB
alpinegear-safehtml.esm.min.js 806 B 543 B 457 B
alpinegear-safehtml.min.js 853 B 569 B 485 B
alpinegear-template.esm.min.js 421 B 294 B 219 B
alpinegear-template.min.js 483 B 326 B 246 B
alpinegear-typegrab.esm.min.js 471 B 333 B 277 B
alpinegear-typegrab.min.js 509 B 348 B 294 B
alpinegear-when.esm.min.js 1.71 KiB 883 B 761 B
alpinegear-when.min.js 1.77 KiB 914 B 787 B

@rameel
rameel merged commit 689d152 into main Oct 25, 2026
2 checks passed
@rameel
rameel deleted the bound/select-options branch October 25, 2026 21:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant