From 63d134d922c39a7c076fdc1f2de8ebe298590196 Mon Sep 17 00:00:00 2001 From: Asad Ali <42726454+dmp990@users.noreply.github.com> Date: Sun, 27 Sep 2026 20:11:00 +0100 Subject: [PATCH] Fix x-model sync for grouped dynamic options --- packages/alpinejs/src/directives/x-model.js | 2 +- packages/docs/src/en/directives/model.md | 22 ++++++++----- .../integration/directives/x-model.spec.js | 31 +++++++++++++++++++ 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/packages/alpinejs/src/directives/x-model.js b/packages/alpinejs/src/directives/x-model.js index 770a12417..480851668 100644 --- a/packages/alpinejs/src/directives/x-model.js +++ b/packages/alpinejs/src/directives/x-model.js @@ -184,7 +184,7 @@ directive('model', (el, { modifiers, expression }, { effect, cleanup }) => { el._x_forceModelUpdate(getValue()) }) - observer.observe(el, { childList: true }) + observer.observe(el, { childList: true, subtree: true }) cleanup(() => observer.disconnect()) } diff --git a/packages/docs/src/en/directives/model.md b/packages/docs/src/en/directives/model.md index 07476ded9..5341fd3b9 100644 --- a/packages/docs/src/en/directives/model.md +++ b/packages/docs/src/en/directives/model.md @@ -259,13 +259,17 @@ Colors: -### Dynamically populated Select Options +### Dynamically populated select options + +`x-model` keeps the selection synchronized when options are added or removed dynamically, including options nested inside an ``. ```alpine Color: @@ -273,11 +277,13 @@ Color:
-
+
Color:
diff --git a/tests/cypress/integration/directives/x-model.spec.js b/tests/cypress/integration/directives/x-model.spec.js index 4933a34e3..b55bc14fc 100644 --- a/tests/cypress/integration/directives/x-model.spec.js +++ b/tests/cypress/integration/directives/x-model.spec.js @@ -738,6 +738,37 @@ test('x-model initializes multiple select values rendered with x-for', html` get('option[value="Yellow"]').should('be.selected') }) +test('x-model initializes select values rendered with x-for inside an optgroup', html` +
+ +
+`, ({ get }) => { + get('select').should(haveValue('Orange')) +}) + +test('x-model re-syncs when x-for adds a matching option inside an optgroup', html` +
+ + + +
+`, ({ get }) => { + get('button').click() + get('select').should(haveValue('Green')) +}) + test('x-model does not fire change handlers when x-for options initialize', html`