Livewire component data corrupted when class is dynamically instantiated
I posted about this last week, but I've significantly narrowed down where the error occurs.
I am using Livewire Datatables (https://github.com/MedicOneSystems/livewire-datatables/) and I need to dynamically build columns based on user input.
Don't worry if you're not familiar with Livewire Datatables, I'll include all the context you need. All it is is a TALL-stack package for creating tables with advanced filtering capabilities by querying a SQL database. Go to https://www.livewire-datatables.com/complex for a quick, live example.
In Livewire Datatables, a table is build like this:
// ...Livewire component stuff above this line
public function columns()
{
return [
DateColumn::name('date')
->label('Date')
->filterable()
->hideable(),
Column::name('devices.name')
->label('Device')
->filterable()
->hideable(),
];
}
After creating a new Datatable Livewire component and doing the necessary config to it, this will query the columns specified in your database and output a table with it. Keep in mind that Livewire Datatables do not have views, only controllers.
So that's the context. Here is my problem. As I said earlier, I need to dynamically build the columns based on user input. From what I can tell this is not really what Livewire Datatables is designed to do, so I'm running into an issue. I've isolated that issue, and here it is:
Take the above example. It works, and it creates a simple two-column HTML table where I can filter on the date and the device column.
Now, below, I have user input coming from a different Livewire component. I am storing that input in an array ($cols), and looping over it to replicate the example above.
(I've put it all here for simplicity's sake, but the problem does not come from the transference of data between components. My issue still happens when all of the data is contained within the datatable component.)
public function columns()
{
$cols = [
[
'column' => 'Mediconesystems\\LivewireDatatables\\DateColumn',
'name' => 'date',
'label' => 'Date',
'filterable' => true,
'hideable' => true,
],
[
'column' => 'Mediconesystems\\LivewireDatatables\\Column',
'name' => 'devices.name',
'label' => 'Devices',
'filterable' => true,
'hideable' => true,
],
];
foreach($cols as $key => $val) {
$instance = app()->make($val['column']);
$columnName = $val['name'];
$column = $instance->name($columnName);
$column->filterable = true;
$column->hideable = true;
array_push($this->cols, $column);
}
return $this->cols;
}
This actually works. It hits the database and builds the table just like the original example. But... as soon as I try to interact with the filtering capabilities or the pagination buttons, it throws the following error:
Livewire encountered corrupt data when trying to hydrate the [MyDatatable] component. Ensure that the [name, id, data] of the Livewire component wasn't tampered with between requests.
My biggest hunch is that it's caused by a difference in how instantiating the column classes like:
foreach($cols as $key => $val) {
$instance = app()->make($val['column']); // Right here
$columnName = $val['name'];
$column = $instance->name($columnName); // Or maybe here
// ...
}
But I don't know. I have used this method to instantiate dynamic classes before, but never ones that needed to be "filtered" like this.
Any ideas? Thanks in advance. I know this is a bit of a weird one. I'm happy to clarify further if needed.
Please or to participate in this conversation.