Skip to content

Commit 09e6243

Browse files
committed
Fix x-model setting .value instead of .checked on checkboxes
1 parent 1735d0b commit 09e6243

3 files changed

Lines changed: 32 additions & 13 deletions

File tree

packages/alpinejs/src/directives/x-model.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,23 @@ directive('model', (el, { modifiers, expression }, { effect, cleanup }) => {
155155
// If nested model key is undefined, set the default value to empty string.
156156
if (value === undefined && typeof expression === 'string' && expression.match(/\./)) value = ''
157157

158-
// @todo: This is nasty
159-
window.fromModel = true
160-
mutateDom(() => bind(el, 'value', value))
161-
delete window.fromModel
158+
mutateDom(() => {
159+
if (isCheckbox(el)) {
160+
if (Array.isArray(value)) {
161+
el.checked = value.some(val => val == el.value)
162+
} else {
163+
el.checked = !!value
164+
}
165+
} else if (isRadio(el)) {
166+
if (typeof value === 'boolean') {
167+
el.checked = safeParseBoolean(el.value) === value
168+
} else {
169+
el.checked = el.value == value
170+
}
171+
} else {
172+
bind(el, 'value', value)
173+
}
174+
})
162175
}
163176

164177
effect(() => {

packages/alpinejs/src/utils/bind.js

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,6 @@ function bindInputValue(el, value) {
4646
if (el.attributes.value === undefined) {
4747
el.value = value
4848
}
49-
50-
// @todo: yuck
51-
if (window.fromModel) {
52-
if (typeof value === 'boolean') {
53-
el.checked = safeParseBoolean(el.value) === value
54-
} else {
55-
el.checked = checkedAttrLooseCompare(el.value, value)
56-
}
57-
}
5849
} else if (isCheckbox(el)) {
5950
// If we are explicitly binding a string to the :value, set the string,
6051
// If the value is a boolean/array/number/null/undefined, leave it alone, it will be set to "on"

tests/cypress/integration/directives/x-model.spec.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,3 +660,18 @@ test('x-model.blur syncs value before form submit handler runs',
660660
}
661661
)
662662

663+
test('x-model with dotted expression does not overwrite checkbox submission value',
664+
html`
665+
<div x-data="{ form: { agree: undefined } }">
666+
<input type="checkbox" name="agree" x-model="form.agree">
667+
</div>
668+
`,
669+
({ get }) => {
670+
get('input').should(haveValue('on'))
671+
get('input').should(notBeChecked())
672+
get('input').check()
673+
get('input').should(beChecked())
674+
get('input').should(haveValue('on'))
675+
}
676+
)
677+

0 commit comments

Comments
 (0)