I am attempting to send two instances of DataTables to my view. The scenario involves having a tab menu with each tab containing a corresponding table. Here is the approach I have taken.
My controller
public function show(AuthorityPage $authorityPage,
AuthorityPageGuideContentDataTable $authorityPageGuideContentDataTable,
AuthorityPageAccordionDataTable $authorityPageAccordionDataTable
)
{
$blogPosts = BlogPost::where('domain_id', getCurrentDomain())->where('is_active',true)
->select(['id','name'])->get();
$tours = Tour::where('domain_id', getCurrentDomain())
->with('generalDetail')->get();
$destinations = Destination::where('domain_id', getCurrentDomain())
->select(['id','name'])->get();
$keywordIntents = [
'i' => 'Informational',
'n' => 'Navigational',
't' => 'Transactional',
'c' => 'Commercial',
];
$accordionDt = $authorityPageAccordionDataTable->with([
'authorityPage' => $authorityPage
])->html();
$authorityContentDt = $authorityPageGuideContentDataTable->with([
'authorityPage' => $authorityPage
])->html();
return view('pages.authority-pages.show', compact(
'authorityPage',
'blogPosts',
'tours',
'destinations',
'keywordIntents',
'authorityContentDt', // first dt
'accordionDt' //2nd dt
));
in my first tab view i render the datatable by
<div class="card-body py-4">
<div class="table-responsive">
{{ $authorityContentDt->table()}}
</div>
</div>
in my second tab
<div class="card-body py-4">
<div class="table-responsive">
{{ $accordionDt->table() }}
</div>
</div>
one of my datatable class (similar to all of my datatable classes)
class AuthorityPageGuideContentDataTable extends DataTable
{
public function dataTable(QueryBuilder $query): EloquentDataTable
{
return (new EloquentDataTable($query))
->editColumn('guide_type', function (DestinationGuideDetails $destinationGuideDetails) {
return DestinationGuideType::byValue($destinationGuideDetails->guide_type)->name;
})
->editColumn('content', function (DestinationGuideDetails $destinationGuideDetails) {
return strip_tags($destinationGuideDetails->content);
})
->addColumn('action', function (DestinationGuideDetails $destinationGuideDetails) {
return '<button class="btn btn-icon btn-active-light-primary w-30px h-30px" onclick="deletedestinationGuideContent('.$this->authorityPage->id.' , '.$destinationGuideDetails->id.')"> '.getIcon("trash","fs-3").'</button>
<button data-bs-toggle="modal" data-bs-target="#kt_modal_1" class="btn btn-icon btn-active-light-primary w-30px h-30px" onclick="getContent('.$this->authorityPage->id.','.$destinationGuideDetails->id.')"> '.getIcon("notepad-edit","fs-3").'</button>';
})
->rawColumns(['action'])
->setRowId(function ($destinationGuideDetails) {
return "destination-guide-details-{$destinationGuideDetails->id}";
});
}
public function query(DestinationGuideDetails $model): QueryBuilder
{
$query = $model->newQuery()
->join('destination_guides', 'destination_guide_details.destination_guide_id', '=', 'destination_guides.id')
->where('destination_guides.guideable_id', $this->authorityPage->id)
->where('destination_guides.guideable_type', 'App\Models\AuthorityPage')
->select('destination_guide_details.*');
return $query;
}
public function html(): HtmlBuilder
{
return $this->builder()
->setTableId('destination-guide-table')
->columns($this->getColumns())
->minifiedAjax()
->dom('rt' . "<'row'<'col-sm-12 col-md-5'l><'col-sm-12 col-md-7'p>>",)
->addTableClass('table align-middle table-row-dashed fs-6 gy-5 dataTable no-footer text-gray-600 fw-semibold')
->setTableHeadClass('text-start text-muted fw-bold fs-7 text-uppercase gs-0');
}
public function getColumns(): array
{
return [
Column::make('guide_type')->name('guide_type'),
Column::make('content')->name('Content'),
Column::make('action')->name('Action')->width('10%'),
];
}
protected function filename(): string
{
return 'AuthorityPageGuideContent_' . date('YmdHis');
}
}
The problem is it returns an alert saying
DataTables warning: table id=destination-guide-table - Invalid JSON response.
For more information about this error, please see http://datatables.net/tn/1
Firstly, set up routes that invoke your DataTable classes:
Route::get('/authority-pages/{authorityPage}/destination-guide', [AuthorityPageController::class, 'getAuthorityPageGuideContentData'])->name('authority-pages-get-destination-guide-content');
Route::get('/authority-pages/{authorityPage}/accordions', [AuthorityPageController::class, 'getAuthorityPageAccordionData'])->name('authority-pages-get-accordions');
In your controller, ensure the methods look like this:
public function getAuthorityPageAccordionData(AuthorityPage $authorityPage, AuthorityPageAccordionDataTable $authorityPageAccordionDataTable)
{
return $authorityPageAccordionDataTable->with([
'authorityPage' => $authorityPage
])->render('pages.authority-pages.show');
}
public function getAuthorityPageGuideContentData(AuthorityPage $authorityPage, AuthorityPageGuideContentDataTable $authorityPageGuideContentDataTable)
{
return $authorityPageGuideContentDataTable->with([
'authorityPage' => $authorityPage
])->render('pages.authority-pages.show');
}
Now, in your show method, call the html() method from the DataTable instance. You can use the resulting variables in your view like this:
$accordionDt = $authorityPageAccordionDataTable->with([
'authorityPage' => $authorityPage
])->html();
$authorityContentDt = $authorityPageGuideContentDataTable->with([
'authorityPage' => $authorityPage
])->html();
return view('pages.authority-pages.show', [
'authorityPage' => $authorityPage,
'blogPosts' => $blogPosts,
'tours' => $tours,
'destinations' => $destinations,
'keywordIntents' => $keywordIntents,
'authorityContentDt' => $authorityContentDt,
'accordionDt' => $accordionDt
]);
Now, within your view, you can use {{$authorityContentDt->table()}}
and {{$authorityContentDt->scripts()}}
to include the DataTable HTML and scripts.