filament
filament copied to clipboard
`KeyValue` `->reorderable()` doesn't work
Package
filament/filament
Package Version
v3.2.16
Laravel Version
v10.41.0
Livewire Version
No response
PHP Version
PHP8.2.15
Problem description
KeyValue::make('meta')
->reorderable()
This should reorder the key/values and save them in the db as such. However when you change the order and reload the page or go back to the edit page. The ordering has not changed
Expected behavior
The Ordering set by the user should be respected
Steps to reproduce
- go to http://filament-issue.test/admin/products/1/edit
- Save an order.
- Go back to http://filament-issue.test/admin/products/1/edit
- Change the order and save.
- Reload and the order has not changed
Reproduction repository
https://github.com/sandersjj/filament-issue
Relevant log output
No response
Duplicate of #9030? Please check your Livewire version
Duplicate of #9030? Please check your Livewire version
I have checked it and I am running livewire v3.4.2.
This Pr has been merged in v3.4.0 so it didn't solve the issue yet.
@sandersjj, have you found the fix yet?
@sandersjj, have you found the fix yet?
No I ended up not using the KeyValue field.
I think the problem itself is in trying to add the ordering to one-dimensional array.
json.org states that:
An object is an unordered set of name/value pairs.
That not only means that order of name/value pairs is (could be) not preserved, but also that two objects which differ only by order of name/value pairs are (should be) considered the same.
On the other hand, php.net states that:
An array in PHP is actually an ordered map.
The order is preserved for string keys, but numeric keys could not be ordered inherently.
Also, as we can see, Livewire tracks changes in JS objects with no regards to name/value pairs order, in order to minimize payload (and imho it's a good choice).
Thus, the KV component itself should either not have "ordering" feature, or change the storage mechanism to "array of objects".
For example, instead of storing as:
{ one: "One", two: "Two" }
it could be:
[ { key: "one", value: "One" }, { key: "two", value: "Two" } ]
This way, the ordering will be preserved both in frontend and backend. Here is the small demonstration: https://wirebox.app/b/41729
change the storage mechanism to "array of objects".
For example, instead of storing as:
{ one: "One", two: "Two" }
it could be:[ { key: "one", value: "One" }, { key: "two", value: "Two" } ]
@danharrin what do you think about this? do you think this can be implemented in v3 with backward compatible or only in v4?
This has been handled in v4 (#13249) by updating the internal data structure as per #12943, and then masking that internal state with a new "cast" to avoid breaking changes to $get()
and $set()
etc.