Fix :value bindings not updating custom elements when bound object data mutates#4833
Fix :value bindings not updating custom elements when bound object data mutates#4833joshhanley wants to merge 1 commit into
:value bindings not updating custom elements when bound object data mutates#4833Conversation
…data mutates `bindInputValue` short-circuits with a reference-equality check (`el.value === value`). For standard inputs this is fine because `el.value` is always a string, but for custom elements that store the bound value as a property, the element's `value` getter returns the reactive proxy that was last set. When the proxy is the same reference between renders (its internals mutate but the top-level reference is preserved), the equality check is true and the setter is never re-invoked. Skip the short-circuit when the value is a non-null object so updates propagate to the custom element.
The reference-equality short-circuit that hid these updates was in Alpine's `bindInputValue`, not Livewire. With that fixed upstream (alpinejs/alpine#4833), the Livewire-side workaround is no longer needed. The test in `MergeSnapshotBrowserTest.php` stays as a regression guard.
|
This is curious, since, of course, normal attributes wouldn't be allowed to be objects, but it is definitely what someone might expect for this kind of thing, especially coming from less "web-native" frameworks. The alternative would be forcefully stringifying it into the attribute...which would then require the element to parse that... But also the fact it's a reactive object being passed could cause other issues just passing the proxy as is...but it would play nice with mutatibility, and leave making it Question: Does this same issue occur for attributes other than I assume this change doesn't change the behavior of assigning to |
The Scenario
When
:value(orx-model) binds an object to a custom element, mutations to nested properties don't propagate to the element:After clicking the button the display still shows
"value":100instead of999.The Problem
bindInputValueshort-circuits with a reference-equality check:The custom element's
valuegetter returns the reactive proxy that was last set. When the proxy is the same reference between renders (its contents mutate but the top-level reference is preserved), the equality check is true and the setter is never re-invoked.The Solution
Skip the short-circuit when
valueis a non-null object:Strings, numbers, booleans, and
null/undefinedstill short-circuit as before.Fixes livewire/flux#2414