Did you try putting the javascript into a div with a "wire:ignore" around it?
"Livewire encountered corrupt data when trying to hydrate component"
This is a very bizarre and complex one, so stay with me.
I am using Livewire Datatables ( https://github.com/MedicOneSystems/livewire-datatables ) to build a custom filtering feature for my analytics dashboard app. This feature presents the user with a list of metrics which they can select, and this selection is passed through the application to build a query that hits the database and returns data to the user, in the form of an HTML table.
Originally I was using it to build a regular HTML table, and all was well. However I am in need of greater filtering abilities on the table itself, which is where Livewire Datatables comes in. If you are unfamiliar with Livewire Datatables, below is a sample of how the columns are structured in a Livewire Datatable component.
<?php
namespace App\Http\Livewire\Traffic;
use App\Models\Traffic;
use Mediconesystems\LivewireDatatables\Column;
use Mediconesystems\LivewireDatatables\DateColumn;
use Mediconesystems\LivewireDatatables\Http\Livewire\LivewireDatatable;
use Mediconesystems\LivewireDatatables\NumberColumn;
class Trafficpivottable extends LivewireDatatable
{
public $model = Display::class;
public function builder()
{
// join to relational tables if necessary
return Traffic::query()
->leftJoin('sites', 'sites.id', 'traffic.sites_id')
->leftJoin('devices', 'devices.id', 'traffic.devices_id');
}
public function columns()
{
return [ // Columns are built here - these will directly correspond to what is queried in the database as well as what is built on the front-end table
DateColumn::name('date')
->label('Date')
->filterable()
->hideable(),
Column::name('sites.name')
->label('Site')
->filterable()
->hideable()
->hide(),
Column::name('devices.name')
->label('Device')
->filterable()
->hideable(),
NumberColumn::name('sessions')
->label('Sessions')
->filterable()
->hideable(),
];
}
}
This goes to the SQL database, grabs those 4 columns and outputs a dynamic HTML table with 4 columns. Pretty straightforward. When hardcoded like this, it works just fine.
My problem is that I need to dynamically build these columns as per the user's input. Below is an illustration of the structure I have so far:
There are two Livewire components here - the Custom Filter which has the vanilla filtering UI that I built, and the Custom Report component which is a Livewire Datatable. Livewire Datatables do not have blade views.
It starts in the Custom Filter Livewire component. The user makes a selection, Javascript in the blade view gathers their selection and passes it to the controller.
// custom-filter.blade.php
Livewire.emit('submitReport', submittedList);
The controller then uses that data to create an array that can be used by the datatable Livewire component to build the columns seen above. At the end, a Livewire emit is called to the datatables component which it passes the column data to.
// CustomFilter.php
public function submitReport($submittedList)
{
$cols = [
[
'column' => 'Mediconesystems\\LivewireDatatables\\DateColumn', // This is called an FQNS - fully qualified namespace. It is necessary for the next step; simply including 'DateColumn' here produces a "no such class exists" error
'name' => 'date',
'label' => 'Date',
'filterable' => true,
'hideable' => true,
],
[
'column' => 'Mediconesystems\\LivewireDatatables\\Column',
'name' => 'sites.name',
'label' => 'Site',
'filterable' => true,
'hideable' => true,
],
[
'column' => 'Mediconesystems\\LivewireDatatables\\Column',
'name' => 'devices.name',
'label' => 'Devices',
'filterable' => true,
'hideable' => true,
],
];
$this->emit('displayReport', $cols);
}
The Livewire Datatable component is given the column data and asked to execute.
// Customreport.php
public function displayReport($cols)
{
foreach($cols as $key => $val) {
$instance = app()->make($val['column']);
$columnName = $val['name'];
$item = $instance->name($columnName);
$item->filterable = true;
$item->hideable = true;
array_push($this->cols, $item);
}
$this->ready = true;
}
public function columns()
{
if ($this->ready) {
return $this->cols; // This is where the query happens. My assumption is that the Livewire component will refresh and $this->ready will be set to true, before this method is called again.
} else {
return [];
}
}
A dd($this->cols) returns exactly what is needed to build the columns, identical to if there was no passing around through components. In other words, it builds the column objects properly.
When I hit the submit button to send it through that chain, the error appears. The full error states: Livewire encountered corrupt data when trying to hydrate the [customreport] component. Ensure that the [name, id, data] of the Livewire component wasn't tampered with between requests.
I looked in the Laravel debugbar and none of those three items seem to change, although all other livewire components dissapear from the debugbar when I click submit. For whatever reason.
I also attempted to move everything to the columns() method and pass the $cols property in there, but that's not allowed. Not compatible with Livewire Datatables I guess.
Can anyone help?! Thank you so much in advance if you even read this far. I spent a good 45 minutes formatting this question, which is a fraction of the the time I've spent banging my head on the wall about this error.
Please or to participate in this conversation.