You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PR #4729 (merged Feb 2, 2026) introduced a cleanup callback in the x-model directive that references el.form._x_pendingModelUpdates. When an input with x-model.blur (or Livewire's wire:model.blur) is removed from the DOM — for example via x-if or Livewire's @if morphing — the element's .form property becomes null because it's no longer attached to a <form>. The cleanup callback then throws:
Uncaught TypeError: Cannot read properties of null (reading '_x_pendingModelUpdates')
This error crashes the entire DOM morph process, which also prevents x-model / wire:model bindings on other elements from being initialized during the same render cycle.
Steps to reproduce
Place an <input x-model.blur="value"> inside an x-if (or Livewire @if) block within a <form>
Trigger a re-render that removes the element from the DOM (e.g., toggle the x-if condition)
Observe the TypeError in the console
Minimal reproduction with Livewire (same applies with pure Alpine x-if):
When the user switches from type "a" to "b", the <input wire:model.blur> is removed during the Livewire morph. The cleanup callback throws because el.form is null.
Root cause
In packages/alpinejs/src/directives/x-model.js, the code added by #4729:
The if (el.form) check correctly guards at registration time, but the cleanup() callback executes later when the element is being torn down. By that point, the element has been detached from its parent form, so el.form returns null.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Description
PR #4729 (merged Feb 2, 2026) introduced a cleanup callback in the
x-modeldirective that referencesel.form._x_pendingModelUpdates. When an input withx-model.blur(or Livewire'swire:model.blur) is removed from the DOM — for example viax-ifor Livewire's@ifmorphing — the element's.formproperty becomesnullbecause it's no longer attached to a<form>. The cleanup callback then throws:This error crashes the entire DOM morph process, which also prevents
x-model/wire:modelbindings on other elements from being initialized during the same render cycle.Steps to reproduce
<input x-model.blur="value">inside anx-if(or Livewire@if) block within a<form>x-ifcondition)Minimal reproduction with Livewire (same applies with pure Alpine
x-if):When the user switches from type "a" to "b", the
<input wire:model.blur>is removed during the Livewire morph. The cleanup callback throws becauseel.formisnull.Root cause
In
packages/alpinejs/src/directives/x-model.js, the code added by #4729:The
if (el.form)check correctly guards at registration time, but thecleanup()callback executes later when the element is being torn down. By that point, the element has been detached from its parent form, soel.formreturnsnull.Suggested fix
Capture the form reference at registration time:
Versions
.formreturnsnullfor detached elements)Beta Was this translation helpful? Give feedback.
All reactions