I'm developing a system which has many tables so I have to repeat the writing of table tags on all the files which display a table Here is what I'm doing on every file which have to display table
On Countries table:
<table class="table table-striped table-hover table-sm" id="table">
<thead class="text-uppercase text-center bg-primary">
<tr class="text-white">
<th scope="col">Name</th>
<th scope="col">Slug</th>
<th scope="col">Population</th>
<th scope="col">Region</th>
<th scope="col">Cities</th>
<th scope="col">Descriptions</th>
<th scope="col" >Actions</th>
</tr>
{{ csrf_field() }}
</thead>
<tbody>
@foreach ($countries as $country)
<tr>
<td class="text-left">{{$country->name}}</td>
<td class="text-center">{{$country->slug}}</td>
<td class="text-right">{{$country->population}}</td>
<td class="text-center">{{$country->region->name}}</td>
<td class="text-center">{{$country->city_count}}</td>
<td class="text-left">{{$country->desc}}</td>
<td class="text-center">
<div class="btn-group">
@can('country-update')
<a class="btn btn-primary btn-sm mr-2" href="{{route('location.countries.edit',$country)}}" title="Edit"><i class="fa fa-edit"></i></a>
@endcan
@can('country-delete')
<form class="form-delete" method="post" action="{{route('location.countries.destroy',$country)}}">
@method('DELETE')
@csrf
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure?')"><i class="fa fa-trash-alt"></i></button>
</form>
@endcan
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
then on the cities I'll do the same but with different table head names and table data
<table class="table table-striped table-hover table-sm" id="table">
<thead class="text-uppercase text-center bg-primary">
<tr class="text-white">
<th scope="col">Name</th>
<th scope="col">Slug</th>
<th scope="col">Country</th>
<th scope="col">Descriptions</th>
<th scope="col" >Actions</th>
</tr>
{{ csrf_field() }}
</thead>
<tbody>
@foreach ($cities as $city)
<tr>
<td class="text-left">{{$city->name}}</td>
<td>{{$city->slug}}</td>
<td class="text-center">{{$city->country->name}}</td>
<td class="text-left">{{$city->desc}}</td>
<td class="text-center">
<div class="btn-group">
@can('city-update')
<a class="btn btn-primary btn-sm mr-3" href="{{route('location.cities.edit',$city)}}" title="Edit"><i class="fa fa-edit"></i></a>
@endcan
@can('city-delete')
<form class="form-delete" method="post" action="{{route('location.cities.destroy',$city)}}">
@method('DELETE')
@csrf
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure?')" title="delete"><i class="fa fa-trash-alt"></i></button>
</form>
@endcan
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
but I wat to have a template where I'll only populate table head rows and table body something like this
<div class="table-responsive">
<table class="table table-striped table-hover table-sm" id="table">
<thead class="text-uppercase text-center">
<tr>
//Dynamic table heads
@if(!is_null($rows))
@foreach($rows as $row)
{{$row}}
@endforeach
@endif
</tr>
</thead>
<body>
//Dynamic table body
@if(!is_null($datas))
@foreach($datas as $data)
{{$data}}
@endforeach
@endif
</tbody>
</table>
<!-- end table -->
</div>
What is the best way to accomplish this
You can use Blade component for that. One of approaches in Laravel 7 is to use Blade class component. Link to official Blade components docs: https://laravel.com/docs/7.x/blade#components
You can create a generic table component using artisan command:
php artisan make:component Table
Your component could look like that:
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class Table extends Component
{
/**
* Array of table heading strings
*
* @var array
*/
public $headings;
/**
* Table rows
*
* @var array
*/
public $rows;
/**
* Create the component instance.
*
* @param string $type
* @param string $message
* @return void
*/
public function __construct($headings, $rows)
{
$this->headings = $headings;
$this->rows = $rows;
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\View\View|string
*/
public function render()
{
return view('components.table');
}
}
Now when you have component class, you have to prepare the component view. You will found it in /resources/views/components/table.blade.php.
<div class="table-responsive">
<table class="table table-striped table-hover table-sm" id="table">
//Dynamic table heads
@if($headings)
<thead class="text-uppercase text-center">
<tr>
@if($rows))
@foreach($rows as $row)
<th>{{$row}}</th>
@endforeach
@endif
</tr>
</thead>
@endif
<tbody>
//Dynamic table body
@foreach($rows as $row)
<tr>
// Render each item from row
@foreach($row as $item)
<td>{{$item}}</td>
@endforeach
</tr>
@endif
</tbody>
</table>
<!-- end table -->
</div>
Now you can use your component in your views:
<x-table :headings="['foo', 'bar']"
:data="[['foo1', 'bar1'], ['foo2', 'bar2']]" class="mt-4"/>