Laravel 8 Jet Live

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 31

Laravel 8 - CRUD basic steps (Livewire and Tailwind)

1. Install Laravel Jetstream dan livewire  laravel new Latihan --jet

2. Seting file .env

3. Buat Database

4. Buat File Migration

php artisan make:migration create_companies_table

<?php

use Illuminate\Database\Migrations\Migration;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Support\Facades\Schema;

class CreateCompaniesTable extends Migration

/**

* Run the migrations.

* @return void

*/

public function up()

Schema::create('companies', function (Blueprint $table) {

$table->id();

$table->string('title')->unique();

$table->timestamps();

});

/**
* Reverse the migrations.

* @return void

*/

public function down()

Schema::dropIfExists('companies');

Run command to add table in database:

php artisan migrate

Run command to create Livewire CRUD files (it will create /app/Http/Livewire/Companies.php and
/resources/views/livewire/companies.blade.php):

php artisan make:livewire companies

In /app/Http/Livewire/Companies.php file add code:

<?php

namespace App\Http\Livewire;

use Livewire\Component;

use App\Models\Company;

class Companies extends Component

public $title;

public $company_id;

public $isOpen = 0;

/**

* The attributes that are mass assignable.

*
* @var array

*/

public function render()

return view('livewire.companies', [

'companies' => Company::orderBy('id', 'desc')]);

/**

* The attributes that are mass assignable.

* @var array

*/

public function create()

$this->resetInputFields();

$this->openModal();

/**

* The attributes that are mass assignable.

* @var array

*/

public function openModal()

$this->isOpen = true;

}
/**

* The attributes that are mass assignable.

* @var array

*/

public function closeModal()

$this->isOpen = false;

/**

* The attributes that are mass assignable.

* @var array

*/

private function resetInputFields(){

$this->title = '';

$this->company_id = '';

/**

* The attributes that are mass assignable.

* @var array

*/

public function store()

$this->validate([

'title' => 'required|unique:companies,title,'.$this->company_id,

]);
$data = array(

'title' => $this->title

);

$company = Company::updateOrCreate(['id' => $this->company_id],$data);

session()->flash('message', $this->company_id ? 'Company updated successfully.' : 'Company


created successfully.');

$this->closeModal();

$this->resetInputFields();

/**

* The attributes that are mass assignable.

* @var array

*/

public function edit($id)

$company = Company::findOrFail($id);

$this->company_id = $id;

$this->title = $company->title;

$this->openModal();

/**

* The attributes that are mass assignable.

* @var array

*/

public function delete($id)

$this->company_id = $id;
Company::find($id)->delete();

session()->flash('message', 'Company deleted successfully.');

In /resources/views/livewire/companies.blade.php file add code

<x-slot name="header">

<h2 class="font-semibold text-xl text-gray-800 leading-tight">

{{ __('Companies') }}

</h2>

</x-slot>

<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">

@if (session()->has('message'))

<div id="alert" class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-green-500">

<span class="inline-block align-middle mr-8">

{{ session('message') }}

</span>

<button class="absolute bg-transparent text-2xl font-semibold leading-none right-0 top-0 mt-


4 mr-6 outline-none focus:outline-none" onclick="document.getElementById('alert').remove();">

<span>×</span>

</button>

</div>

@endif

<button wire:click="create()" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4


rounded mt-10">Create New Company</button>

@if (count($companies)>0)

<div class="py-10">

<div class="inline-block min-w-full shadow rounded-lg overflow-hidden">

<table class="min-w-full leading-normal">

<thead>

<tr>

<th
class="px-5 py-3 border-b-2 border-black bg-black text-left text-xs font-semibold
text-white uppercase tracking-wider">

{{ __('Title') }}

</th>

<th

class="px-5 py-3 border-b-2 border-black bg-black text-left text-xs font-semibold


text-white uppercase tracking-wider">

</th>

</tr>

</thead>

<tbody>

@foreach($companies as $company)

<tr>

<td class="px-5 py-5 bg-white text-sm @if (!$loop->last) border-gray-200 border-b


@endif">

{{ Str::limit($company->title, 25) }}

</td>

<td class="px-5 py-5 bg-white text-sm @if (!$loop->last) border-gray-200 border-b


@endif text-right">

<div class="inline-block whitespace-no-wrap">

<button wire:click="edit({{ $company->id }})" class="bg-blue-500 hover:bg-


blue-700 text-white font-bold py-2 px-4 rounded">Edit</button>

<button wire:click="$emit('triggerDelete',{{ $company->id }})" class="bg-red-


500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">Delete</button>

</div>

</td>

</tr>

@endforeach

</tbody>

</table>

</div>

</div>

@endif
@if($isOpen)

<div class="fixed z-100 w-full h-full bg-gray-500 opacity-75 top-0 left-0"></div>

<div class="fixed z-101 w-full h-full top-0 left-0 overflow-y-auto">

<div class="table w-full h-full py-6">

<div class="table-cell text-center align-middle">

<div class="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">

<div class="bg-white rounded-lg text-left overflow-hidden shadow-xl">

<form>

<div class="px-4 pt-5 pb-4 sm:p-6 sm:pb-4">

<div class="flex flex-wrap -mx-3 mb-6">

<div class="w-full md:w-1/2 px-3 mb-6 md:mb-0">

<label for="titleInput" class="block text-gray-700 text-sm font-bold mb-


2">Title:</label>

<input type="text" class="shadow appearance-none border rounded w-full py-2


px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="titleInput"
placeholder="Enter Title" wire:model="title">

@error('title') <span class="text-red-500">{{ $message }}</span>@enderror

</div>

</div>

</div>

<div class="px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">

<span class="flex w-full sm:ml-3 sm:w-auto">

<button wire:click.prevent="store()" type="button" class="inline-flex bg-blue-


500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Save</button>

</span>

<span class="mt-3 flex w-full sm:mt-0 sm:w-auto">

<button wire:click="closeModal()" type="button" class="inline-flex bg-white


hover:bg-gray-200 border border-gray-300 text-gray-500 font-bold py-2 px-4
rounded">Cancel</button>

</span>

</div>

</form>

</div>
</div>

</div>

</div>

</div>

@endif

</div>

@push('styles')

<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/sweetalert2@10/dist/sweetalert2.min.css">

@endpush

@push('scripts')

<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script>

<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.js"></script>

<script type="text/javascript">

document.addEventListener('DOMContentLoaded', function () {

@this.on('triggerDelete', companyId => {

Swal.fire({

title: 'Are You Sure?',

text: 'Company record will be deleted!',

type: "warning",

showCancelButton: true,

confirmButtonColor: '#d33',

cancelButtonColor: '#3085d6',

confirmButtonText: 'Delete!'

}).then((result) => {

if (result.value) {

@this.call('delete',companyId)

} else {
console.log("Canceled");

});

});

})

</script>

@endpush

Our javascript code has to be between tags:

@push('scripts') ... @endpush

and style

@push('styles') ... @endpush

It means in

/resources/views/layouts/app.blade.php

need to add @stack('styles') and @stack('scripts')

<!DOCTYPE html>

<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1">

<meta name="csrf-token" content="{{ csrf_token() }}">

<title>{{ config('app.name', 'Laravel') }}</title>

<!-- Fonts -->

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?


family=Nunito:wght@400;600;700&display=swap">

<!-- Styles -->

<link rel="stylesheet" href="{{ asset('css/app.css') }}">

@livewireStyles
@stack('styles')

<!-- Scripts -->

<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.js" defer></script>

</head>

<body class="font-sans antialiased">

<div class="min-h-screen bg-gray-100">

@livewire('navigation-dropdown')

<!-- Page Heading -->

<header class="bg-white shadow">

<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">

{{ $header }}

</div>

</header>

<!-- Page Content -->

<main>

{{ $slot }}

</main>

</div>

@stack('modals')

@livewireScripts

@stack('scripts')

</body>

</html>

Run command to create Company Model:


php artisan make:model Company

In /app/Models/Company.php file add code:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;

use Illuminate\Database\Eloquent\Model;

class Company extends Model

use HasFactory;

protected $fillable = [

'title'

];

In /routes/web.php need to add route:

Route::middleware(['auth:sanctum', 'verified'])->get('/companies',
App\Http\Livewire\Companies::class)->name('companies');

And run command to clean route cache:

php artisan route:cache

And in the last step need to add companies pages link to main menu. In
/resources/views/navigation-dropdown.blade.php add menu item:

<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">

<x-jet-nav-link href="{{ route('companies') }}" :active="request()->routeIs('companies')">

{{ __('Companies') }}

</x-jet-nav-link>

</div>

And in the same file, where is comment <!-- Responsive Navigation Menu --> add:

<x-jet-responsive-nav-link href="{{ route('companies') }}" :active="request()->routeIs('companies')">

{{ __('Companies') }}
</x-jet-responsive-nav-link>

Laravel 8 - advanced CRUD (Livewire and Tailwind)

#laravel #livewire #crud #tailwindcss

dariusdauskurdis profile image

Darius Dauskurdis

Dec 24, 2020 ・Updated on Feb 17 ・12 min read

Laravel 8 - Livewire CRUD (2 Part Series)

Laravel 8 - CRUD basic steps (Livewire and Tailwind)

Laravel 8 - advanced CRUD (Livewire and Tailwind)

We will continue previous Laravel 8 - CRUD basic steps (Livewire and Tailwind) tutorial. But this time,
we will try to make our CRUD more advanced.

Let's add more fields in companies table. We can continue editing old (if didn't migrate) or create
new migration file. We want to add extra fields for information about which user created or updated
company. So migration file should look like:

<?php

use Illuminate\Database\Migrations\Migration;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Support\Facades\Schema;

class CreateCompaniesTable extends Migration

/**

* Run the migrations.

* @return void

*/

public function up()


{

Schema::create('companies', function (Blueprint $table) {

$table->id();

$table->string('title')->unique();

$table->bigInteger('created_by')->nullable()->unsigned();

$table->foreign('created_by')->references('id')->on('users')->onDelete('set null');

$table->bigInteger('updated_by')->nullable()->unsigned();

$table->foreign('updated_by')->references('id')->on('users')->onDelete('set null');

$table->timestamps();

});

/**

* Reverse the migrations.

* @return void

*/

public function down()

Schema::dropIfExists('companies');

Run command to add table in database:

php artisan migrate

In app/Models/Company.php file need to add new fillable fields, and add "boot" method to run
specific actions automatically when user will create or update company.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

use Illuminate\Support\Facades\Auth;

class Company extends Model

use HasFactory;

protected $fillable = [

'title', 'created_by', 'updated_by'

];

/**

* This is model Observer which helps to do the same actions automatically when you creating or
updating models

* @var array

*/

protected static function boot()

parent::boot();

static::creating(function ($model) {

$model->created_by = Auth::id();

$model->updated_by = Auth::id();

});

static::updating(function ($model) {

$model->updated_by = Auth::id();

});

Let's upgrade our /app/Http/Livewire/Companies.php file. At first need to fix error messages. When
user submit form and forgot to fill fields, he will see errors and when if form will be closed and
opened again, these errors still will be visible. So in "openModal()" method need to add two lines of
code:

$this->resetErrorBag();

$this->resetValidation();

If we have only few companies, no problem. But if users will add many companies, we need to add
pages. Let's say we need to show 10 companies per page. At first need to add "WithPagination" trait
provided by Livewire.

use Livewire\WithPagination;

And inside class "Companies" add

use WithPagination;

Add extra paginate method on an Eloquent query. public function render() { return
view('livewire.companies', [ 'companies' => Company::orderBy('id', 'desc')->paginate(10) ]); }

So now our /app/Http/Livewire/Companies.php file looks like:

<?php

namespace App\Http\Livewire;

use Livewire\Component;

use App\Models\Company;

use Livewire\WithPagination;

use Illuminate\Support\Facades\Auth;

class Companies extends Component

use WithPagination;

public $title;

public $company_id;

public $isOpen = 0;
/**

* The attributes that are mass assignable.

* @var array

*/

public function render()

return view('livewire.companies', [

'companies' => Company::orderBy('id', 'desc')->paginate(10)

]);

/**

* The attributes that are mass assignable.

* @var array

*/

public function create()

$this->resetInputFields();

$this->openModal();

/**

* The attributes that are mass assignable.

* @var array

*/
public function openModal()

$this->isOpen = true;

// Clean errors if were visible before

$this->resetErrorBag();

$this->resetValidation();

/**

* The attributes that are mass assignable.

* @var array

*/

public function closeModal()

$this->isOpen = false;

/**

* The attributes that are mass assignable.

* @var array

*/

private function resetInputFields(){

$this->title = '';

$this->company_id = '';

/**

* The attributes that are mass assignable.

*
* @var array

*/

public function store()

$this->validate([

'title' => 'required|unique:companies,title,'.$this->company_id,

]);

$data = array(

'title' => $this->title

);

$company = Company::updateOrCreate(['id' => $this->company_id],$data);

session()->flash('message', $this->company_id ? 'Company updated successfully.' : 'Company


created successfully.');

$this->closeModal();

$this->resetInputFields();

/**

* The attributes that are mass assignable.

* @var array

*/

public function edit($id)

$company = Company::findOrFail($id);

$this->company_id = $id;

$this->title = $company->title;

$this->openModal();

}
/**

* The attributes that are mass assignable.

* @var array

*/

public function delete($id)

$this->company_id = $id;

Company::find($id)->delete();

session()->flash('message', 'Company deleted successfully.');

In /resources/views/livewire/companies.blade.php file under the table need to add pagination.

{{ $companies->links('pagination',['is_livewire' => true]) }}

We are using not default pagination template, we want to use customised with tailwind. So need to
create new file /resources/views/pagination.blade.php and paste inside code:

@if ($paginator->hasPages())

<nav role="navigation" aria-label="{{ __('Pagination Navigation') }}" class="px-5 py-5 bg-white


border-t flex flex-col xs:flex-row items-center xs:justify-between ">

<div class="flex justify-between flex-1 sm:hidden">

@if ($paginator->onFirstPage())

<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500


bg-white border border-gray-300 cursor-default leading-5 rounded-md">

{!! __('pagination.previous') !!}

</span>

@else

@if (isset($is_livewire))

<button wire:click="previousPage" dusk="previousPage.before" class="relative inline-flex


items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300
leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:shadow-outline-blue
focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">

{!! __('pagination.previous') !!}


</button>

@else

<a href="{{ $paginator->previousPageUrl() }}" class="relative inline-flex items-center px-4


py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md
hover:text-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 active:bg-
gray-100 active:text-gray-700 transition ease-in-out duration-150">

{!! __('pagination.previous') !!}

</a>

@endif

@endif

@if ($paginator->hasMorePages())

@if (isset($is_livewire))

<button wire:click="nextPage" dusk="nextPage.before" class="relative inline-flex items-


center px-4 py-2 ml-3 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-
5 rounded-md hover:text-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-
300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">

{!! __('pagination.next') !!}

</button>

@else

<a href="{{ $paginator->nextPageUrl() }}" class="relative inline-flex items-center px-4 py-2


ml-3 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md
hover:text-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 active:bg-
gray-100 active:text-gray-700 transition ease-in-out duration-150">

{!! __('pagination.next') !!}

</a>

@endif

@else

<span class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-
500 bg-white border border-gray-300 cursor-default leading-5 rounded-md">

{!! __('pagination.next') !!}

</span>

@endif

</div>
<div class="px-5 py-5 bg-white flex flex-col xs:flex-row items-center xs:justify-between">

<div>

<p class="text-xs xs:text-sm text-gray-900">{!! __('Showing') !!} <span class="font-


medium">{{ $paginator->firstItem() }}</span> {!! __('to') !!} <span class="font-
medium">{{ $paginator->lastItem() }}</span> {!! __('of') !!} <span></span><span class="font-
medium">{{ $paginator->total() }}</span> {!! __('results') !!}</p>

</div>

<div class="inline-flex mt-2 xs:mt-0">

<span class="relative z-0 inline-flex shadow-sm rounded-md">

{{-- Previous Page Link --}}

@if ($paginator->onFirstPage())

<span aria-disabled="true" aria-label="{{ __('pagination.previous') }}">

<span class="relative inline-flex items-center px-2 py-2 text-sm font-medium text-


gray-500 bg-white border border-gray-300 cursor-default rounded-l-md leading-5" aria-
hidden="true">

<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">

<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293


3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" />

</svg>

</span>

</span>

@else

@if (isset($is_livewire))

<button wire:click="previousPage" dusk="previousPage.after" rel="prev"


class="relative inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border
border-gray-300 rounded-l-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none
focus:border-blue-300 focus:shadow-outline-blue active:bg-gray-100 active:text-gray-500 transition
ease-in-out duration-150" aria-label="{{ __('pagination.previous') }}">

<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">

<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293


3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" />

</svg>

</button>
@else

<a href="{{ $paginator->previousPageUrl() }}" rel="prev" class="relative inline-flex


items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300
rounded-l-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:border-blue-300
focus:shadow-outline-blue active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-
150" aria-label="{{ __('pagination.previous') }}">

<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">

<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293


3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" />

</svg>

</a>

@endif

@endif

{{-- Pagination Elements --}}

@foreach ($elements as $element)

{{-- "Three Dots" Separator --}}

@if (is_string($element))

<span aria-disabled="true">

<span class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-


medium text-gray-700 bg-white border border-gray-300 cursor-default leading-
5">{{ $element }}</span>

</span>

@endif

{{-- Array Of Links --}}

@if (is_array($element))

@foreach ($element as $page => $url)

@if ($page == $paginator->currentPage())

<span aria-current="page">

<span class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-


medium text-gray-500 bg-white border border-gray-300 cursor-default leading-
5">{{ $page }}</span>

</span>
@else

@if (isset($is_livewire))

<button wire:click="gotoPage({{ $page }})" class="relative inline-flex items-


center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300
leading-5 hover:text-gray-500 focus:z-10 focus:outline-none focus:border-blue-300 focus:shadow-
outline-blue active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150" aria-
label="{{ __('Go to page :page', ['page' => $page]) }}">

{{ $page }}

</button>

@else

<a href="{{ $url }}" class="relative inline-flex items-center px-4 py-2 -ml-px
text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 hover:text-gray-500
focus:z-10 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:bg-gray-100
active:text-gray-700 transition ease-in-out duration-150" aria-label="{{ __('Go to page :page', ['page'
=> $page]) }}">

{{ $page }}

</a>

@endif

@endif

@endforeach

@endif

@endforeach

{{-- Next Page Link --}}

@if ($paginator->hasMorePages())

@if (isset($is_livewire))

<button wire:click="nextPage" dusk="nextPage.after" rel="next" class="relative


inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-
gray-300 rounded-r-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:border-
blue-300 focus:shadow-outline-blue active:bg-gray-100 active:text-gray-500 transition ease-in-out
duration-150" aria-label="{{ __('pagination.next') }}">

<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">

<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293


6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />

</svg>

</button>
@else

<a href="{{ $paginator->nextPageUrl() }}" rel="next" class="relative inline-flex items-


center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300
rounded-r-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:border-blue-300
focus:shadow-outline-blue active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-
150" aria-label="{{ __('pagination.next') }}">

<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">

<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293


6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />

</svg>

</a>

@endif

@else

<span aria-disabled="true" aria-label="{{ __('pagination.next') }}">

<span class="relative inline-flex items-center px-2 py-2 -ml-px text-sm font-medium


text-gray-500 bg-white border border-gray-300 cursor-default rounded-r-md leading-5" aria-
hidden="true">

<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">

<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293


6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />

</svg>

</span>

</span>

@endif

</span>

</div>

</div>

</nav>

@endif

Let's come back to /resources/views/livewire/companies.blade.php file. When user will click button
"Create new company" will popup modal. If we are thinking to use this modal in other places, need
to create standard modal style (frame), which we can use with different content. For now we need
modal with form fields to set information about company. In Laravel 8 we can easy create
components.

php artisan make:component CustomisedModal


It will create two files: /app/View/Components/CustomisedModal.php and
/resources/views/components/customised-modal.blade.php. In
resources/views/components/customised-modal.blade.php add code:

<div class="fixed z-100 w-full h-full bg-gray-500 opacity-75 top-0 left-0"></div>

<div class="fixed z-101 w-full h-full top-0 left-0 overflow-y-auto">

<div class="table w-full h-full py-6">

<div class="table-cell text-center align-middle">

<div class="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">

<div class="bg-white rounded-lg text-left overflow-hidden shadow-xl">

{{ $content }}

</div>

</div>

</div>

</div>

</div>

If we will open /app/View/Components/CustomisedModal.php file we will see code

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class CompanyItem extends Component

/**

* Create a new component instance.

* @return void

*/

public function __construct()

//
}

/**

* Get the view / contents that represent the component.

* @return \Illuminate\Contracts\View\View|string

*/

public function render()

return view('components.customised-modal');

Now we can call this component by using tags (tag name x- and name of view)

<x-customised-modal>...</x-customised-modal>

But we have additional variable $content, it means we need to add x-slot tag with name "content"
and add inside our form.

<x-customised-modal>

<x-slot name="content">

My form

</x-slot>

</x-customised-modal>

In general our /resources/views/livewire/companies.blade.php file should look like:

<x-slot name="header">

<h2 class="font-semibold text-xl text-gray-800 leading-tight">

{{ __('Companies') }}

</h2>

</x-slot>

<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">

@if (session()->has('message'))

<div id="alert" class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-green-500">

<span class="inline-block align-middle mr-8">


{{ session('message') }}

</span>

<button class="absolute bg-transparent text-2xl font-semibold leading-none right-0 top-0 mt-


4 mr-6 outline-none focus:outline-none" onclick="document.getElementById('alert').remove();">

<span>×</span>

</button>

</div>

@endif

<button wire:click="create()" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4


rounded mt-10">Create New Company</button>

@if (count($companies)>0)

<div class="py-10">

<div class="inline-block min-w-full shadow rounded-lg overflow-hidden">

<table class="min-w-full leading-normal">

<thead>

<tr>

<th

class="px-5 py-3 border-b-2 border-black bg-black text-left text-xs font-semibold


text-white uppercase tracking-wider">

{{ __('Title') }}

</th>

<th

class="px-5 py-3 border-b-2 border-black bg-black text-left text-xs font-semibold


text-white uppercase tracking-wider">

</th>

</tr>

</thead>

<tbody>

@foreach($companies as $company)

<tr>

<td class="px-5 py-5 bg-white text-sm @if (!$loop->last) border-gray-200 border-b


@endif">

{{ Str::limit($company->title, 25) }}
</td>

<td class="px-5 py-5 bg-white text-sm @if (!$loop->last) border-gray-200 border-b


@endif text-right">

<div class="inline-block whitespace-no-wrap">

<button wire:click="edit({{ $company->id }})" class="bg-blue-500 hover:bg-


blue-700 text-white font-bold py-2 px-4 rounded">Edit</button>

<button wire:click="$emit('triggerDelete',{{ $company->id }})" class="bg-red-


500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">Delete</button>

</div>

</td>

</tr>

@endforeach

</tbody>

</table>

{{ $companies->links('pagination',['is_livewire' => true]) }}

</div>

</div>

@endif

@if($isOpen)

<x-customised-modal>

<x-slot name="content">

<form>

<div class="px-4 pt-5 pb-4 sm:p-6 sm:pb-4">

<div class="flex flex-wrap -mx-3 mb-6">

<div class="w-full md:w-1/2 px-3 mb-6 md:mb-0">

<label for="titleInput" class="block text-gray-700 text-sm font-bold mb-


2">Title:</label>

<input type="text" class="shadow appearance-none border rounded w-full py-2


px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="titleInput"
placeholder="Enter Title" wire:model="title">

@error('title') <span class="text-red-500">{{ $message }}</span>@enderror

</div>

</div>
</div>

<div class="px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">

<span class="flex w-full sm:ml-3 sm:w-auto">

<button wire:click.prevent="store()" type="button" class="inline-flex bg-blue-500


hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Save</button>

</span>

<span class="mt-3 flex w-full sm:mt-0 sm:w-auto">

<button wire:click="closeModal()" type="button" class="inline-flex bg-white


hover:bg-gray-200 border border-gray-300 text-gray-500 font-bold py-2 px-4
rounded">Cancel</button>

</span>

</div>

</form>

</x-slot>

</x-customised-modal>

@endif

</div>

@push('styles')

<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/sweetalert2@10/dist/sweetalert2.min.css">

@endpush

@push('scripts')

<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script>

<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.js"></script>

<script type="text/javascript">

document.addEventListener('DOMContentLoaded', function () {

@this.on('triggerDelete', companyId => {

Swal.fire({

title: 'Are You Sure?',


text: 'Company record will be deleted!',

type: "warning",

showCancelButton: true,

confirmButtonColor: '#d33',

cancelButtonColor: '#3085d6',

confirmButtonText: 'Delete!'

}).then((result) => {

if (result.value) {

@this.call('delete',companyId)

} else {

console.log("Canceled");

});

});

})

</script>

@endpush

You might also like