Register User Modal using Livewire & TailwindCSS

Tailwind CSS Alpine JS Livewire

Demo

This is a pro component. Get Livewiredemos pro access to view / download the component code.

Component Class


<?php

namespace App\Http\Livewire;

use App\Models\User;
use Livewire\Component;
use Illuminate\Support\Facades\Hash;

class AddNewUserComponent extends Component
{
    protected $listeners = ['showModal'];

    public $showModal = false;
    public $name;
    public $email;
    public $password;
    public $password_confirmation;

    protected $rules = [
        'name' => ['required', 'string', 'max:255'],
        'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
        'password' => ['required', 'string', 'min:8', 'confirmed'],
    ];

    public function showModal(){
        $this->showModal = true;
    }

    public function render()
    {
        return view('livewire.add-new-user-component');
    }

    public function addUser(){
        
        $this->validate();
        try{
            User::create([
                'name' => $this->name,
                'email' => $this->email,
                'password' => Hash::make($this->password)
            ]);
            $this->reset();
            $this->emit('refreshComponent');
            $this->showModal = false;
            $this->emit('successAlert', 'New User Created');
        }catch(\Exception $e){
            $this->addError('error', $e->getMessage());
        }
    }

    public function closeModal(){
        $this->reset();
        $this->resetErrorBag();
    }
}

Component View File


<div x-data="{
    show: @entangle('showModal')
 }" x-show="show" x-cloak>
<div class="tw-fixed tw-z-10 tw-inset-0 tw-overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
  <div class="tw-flex tw-items-end tw-justify-center tw-min-h-screen tw-pt-4 tw-px-4 tw-pb-20 tw-text-center sm:tw-block sm:tw-p-0">
    
    <div class="tw-fixed tw-inset-0 tw-bg-gray-500 tw-bg-opacity-75 tw-transition-opacity" aria-hidden="true"></div>

    <!-- This element is to trick the browser into centering the modal tw-contents. -->
    <span class="tw-hidden sm:tw-inline-block sm:tw-align-middle sm:tw-h-screen" aria-hidden="true">&#8203;</span>

    <div class="tw-inline-block tw-align-bottom tw-bg-white tw-rounded-lg tw-text-left tw-overflow-hidden tw-shadow-xl tw-transform tw-transition-all sm:tw-my-8 sm:tw-align-middle sm:tw-max-w-lg sm:tw-w-full">
      <div class="tw-bg-white tw-px-4 tw-pt-5 tw-pb-4 sm:tw-p-6 sm:tw-pb-4">
        <div class="sm:tw-flex md:tw-items-center sm:tw-items-start">
          <div class="tw-mx-auto tw-flex-shrink-0 tw-flex tw-items-center tw-justify-center tw-h-12 tw-w-12 tw-rounded-full tw-bg-green-100 sm:tw-mx-0 sm:tw-h-10 sm:tw-w-10">
            <!-- Heroicon name: outline/exclamation -->
            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20.822 18.096c-3.439-.794-6.641-1.49-5.09-4.418 4.719-8.912 1.251-13.678-3.732-13.678-5.081 0-8.464 4.949-3.732 13.678 1.597 2.945-1.725 3.641-5.09 4.418-2.979.688-3.178 2.143-3.178 4.663l.005 1.241h10.483l.704-3h1.615l.704 3h10.483l.005-1.241c.001-2.52-.198-3.975-3.177-4.663zm-8.231 1.904h-1.164l-.91-2h2.994l-.92 2z"/></svg>
          </div>
          <div class="tw-mt-3 tw-text-center sm:tw-mt-0 sm:tw-ml-4 sm:tw-text-left">
            <h3 class="tw-text-lg tw-leading-6 tw-font-medium tw-text-gray-900" id="modal-title">
              Add New User
            </h3>
          </div>
        </div>
        @error('error') 
        <div class="tw-bg-red-100 tw-border tw-my-2 tw-border-red-400 tw-text-red-700 px-4 tw-py-2 tw-rounded tw-relative" role="alert">
          <span class="block sm:inline">{{ $message }}</span>
        </div>
        @enderror

        <div class="tw-mt-2 tw-w-full">
              <div class="tw-flex tw-flex-wrap tw--mx-3 tw-my-6">
                <div class="tw-w-full tw-px-3">
                  <label class="tw-block tw-uppercase tw-tracking-wide tw-text-gray-700 tw-text-xs tw-font-bold tw-mb-2" for="grid-password">
                    Name
                  </label>
                  <input wire:model.defer="name" class="tw-appearance-none tw-block tw-w-full tw-bg-gray-200 tw-text-gray-700 tw-border tw-border-gray-200 tw-rounded tw-py-3 tw-px-4 tw-mb-3 tw-leading-tight focus:tw-outline-none focus:tw-bg-white focus:tw-border-gray-500" id="grid-password" type="text" placeholder="Provide User's Name">
                  @error('name') <span class="error tw-text-red-400">{{ $message }}</span> @enderror
                </div>
              </div>
        </div>
        <div class="tw-mt-2 tw-w-full">
              <div class="tw-flex tw-flex-wrap tw--mx-3 tw-my-6">
                <div class="tw-w-full tw-px-3">
                  <label class="tw-block tw-uppercase tw-tracking-wide tw-text-gray-700 tw-text-xs tw-font-bold tw-mb-2" for="grid-password">
                    Email
                  </label>
                  <input wire:model.defer="email" class="tw-appearance-none tw-block tw-w-full tw-bg-gray-200 tw-text-gray-700 tw-border tw-border-gray-200 tw-rounded tw-py-3 tw-px-4 tw-mb-3 tw-leading-tight focus:tw-outline-none focus:tw-bg-white focus:tw-border-gray-500" id="grid-password" type="email" placeholder="Provide User's Email">
                  @error('email') <span class="error tw-text-red-400">{{ $message }}</span> @enderror
                </div>
              </div>
        </div>
        <div class="tw-mt-2 tw-w-full">
              <div class="tw-flex tw-flex-wrap tw--mx-3 tw-my-6">
                <div class="tw-w-full tw-px-3">
                  <label class="tw-block tw-uppercase tw-tracking-wide tw-text-gray-700 tw-text-xs tw-font-bold tw-mb-2" for="grid-password">
                    Password
                  </label>
                  <input wire:model.defer="password" class="tw-appearance-none tw-block tw-w-full tw-bg-gray-200 tw-text-gray-700 tw-border tw-border-gray-200 tw-rounded tw-py-3 tw-px-4 tw-mb-3 tw-leading-tight focus:tw-outline-none focus:tw-bg-white focus:tw-border-gray-500" id="grid-password" type="password" placeholder="Provide User's Password">
                  <p class="tw-text-gray-600 tw-text-xs tw-italic">Should be of minimum 6 characters.</p>
                  @error('password') <span class="error tw-text-red-400">{{ $message }}</span> @enderror
                </div>
              </div>
        </div>
        <div class="tw-mt-2 tw-w-full">
              <div class="tw-flex tw-flex-wrap tw--mx-3 tw-my-6">
                <div class="tw-w-full tw-px-3">
                  <label class="tw-block tw-uppercase tw-tracking-wide tw-text-gray-700 tw-text-xs tw-font-bold tw-mb-2" for="grid-password">
                    Confirm Password
                  </label>
                  <input wire:model.defer="password_confirmation" class="tw-appearance-none tw-block tw-w-full tw-bg-gray-200 tw-text-gray-700 tw-border tw-border-gray-200 tw-rounded tw-py-3 tw-px-4 tw-mb-3 tw-leading-tight focus:tw-outline-none focus:tw-bg-white focus:tw-border-gray-500" id="grid-password" type="password" placeholder="Retype password">
                </div>
              </div>
        </div>
      </div>
      <div class="tw-bg-gray-50 tw-px-4 tw-py-3 sm:tw-px-6 sm:tw-flex sm:tw-flex-row-reverse">
        <button wire:click="addUser" type="button" class="tw-w-full tw-inline-flex tw-justify-center tw-rounded-md tw-border tw-border-transparent tw-shadow-sm tw-px-4 tw-py-2 tw-bg-green-600 tw-text-base tw-font-medium tw-text-white hover:tw-bg-green-700 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-offset-2 focus:tw-ring-green-500 sm:tw-ml-3 sm:tw-w-auto sm:tw-text-sm">
          Add User
        </button>
        <button wire:click="closeModal" x-on:click="show = false" type="button" class="tw-mt-3 tw-w-full tw-inline-flex tw-justify-center tw-rounded-md tw-border tw-border-gray-300 tw-shadow-sm tw-px-4 tw-py-2 tw-bg-white tw-text-base tw-font-medium tw-text-gray-700 hover:tw-bg-gray-50 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-offset-2 focus:tw-ring-indigo-500 sm:tw-mt-0 sm:tw-ml-3 sm:tw-w-auto sm:tw-text-sm">
          Cancel
        </button>
      </div>
    </div>
  </div>
</div>

Usage

You need to include the create user modal component in the file from where you want to invoke the modal. Include it in the global template if you want the modal to be opened up from anywhere in your application.


@livewire('add-new-user-component')

To show the modal you need to pass the information using events. For example as shown in the demo above to open it on click of a button you can do it like below.


  <button x-data={} x-on:click="window.livewire.emitTo('add-new-user-component','showModal')" class="btn btn-primary text-white">Add New User</button>

Download Code

Download the Component class, view file and other required files

This is a pro component. Get Livewiredemos pro access to view / download the component code.