livewire: Getting an error when trying to load a livewire modal with form component
Introduction
I’m creating a crud functionality within the livewire stack. I’m getting the following error when I am trying to load the create.blade.php component as modal using alpine.js. Its working perfectly when I use @include('livewire.user-base.user.create') but it ain’t working and throwing a set of error when trying to load the same thing as a livewire component using <livewire:user-base.user.create /> .
Error Which I’m Getting In The Console
Uncaught (in promise) TypeError: Cannot read property 'replace' of null
at alpinifyElementsForMorphdom (SupportAlpine.js:143)
at onBeforeElUpdated (index.js:461)
at callHook (morphdom.js:35)
at morphEl (morphdom.js:199)
at morphdom.js:463
at Component.value (index.js:368)
at Component.value (index.js:277)
at Component.value (index.js:248)
at Connection.value (index.js:7)
at index.js:50

Source Code
- Index.php
<?php
namespace App\Http\Livewire\UserBase\User;
use Livewire\Component;
use Livewire\WithPagination;
use App\Models\User;
use App\Models\Role;
class Index extends Component
{
use WithPagination;
public function render()
{
$users = User::latest()->paginate(5);
return view('livewire.user-base.user.index', ['users' => $users]);
}
public function edit($id)
{
$users = User::findOrFail($id);
return redirect()->route('user.edit', compact('id'));
}
public function delete($id)
{
$users = User::findOrFail($id);
$users->Roles()->detach();
$users->delete();
session()->flash('delete','User Deleted Successfully');
}
}
- Create.php
<?php
namespace App\Http\Livewire\UserBase\User;
use Livewire\Component;
use App\Models\User;
use App\Models\Role;
use Illuminate\Support\Facades\Hash;
class Create extends Component
{
public $name;
public $email;
public $password;
public $role;
public function render()
{
$roles = Role::all();
return view('livewire.user-base.user.create', ['roles' => $roles]);
}
public function store()
{
$this->validate(
[
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string',
'role' => 'required'
]
);
$user = User::create([
'name' => $this->name,
'email' => $this->email,
'password' => Hash::make($this->password)
]);
$user->Roles()->sync($this->role);
session()->flash('success', 'User Created Successfully');
}
public function cancel()
{
return redirect()->route('user.index');
}
}
- index.blade.php
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
Manage User
</h2>
</x-slot>
<div>
<div class="py-12">
<div class="mx-auto max-w-5xl px-6 lg:px-8">
<div x-data="{ open: false }">
<button @click="open = true" class="inline-flex justify-center w-20 rounded-md border border-gray-300 px-4 py-2 bg-gray-200 font-medium text-gray-700 shadow-sm hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue transition ease-in-out duration-150 text-sm leading-5">Create</button>
<livewire:user-base.user.create />
</div>
@if(session()->has('success'))
<div class="bg-green-200 border border-green-400 rounded-lg mb-8 px-6 py-4">
<div>
<h1 class="text-green-500 text-sm leading-5">{{ session('success') }}</h1>
</div>
</div>
@endif
@if(session()->has('delete'))
<div class="bg-red-200 border border-red-400 rounded-lg mb-8 px-6 py-4">
<div>
<h1 class="text-red-500 text-sm leading-5">{{ session('delete') }}</h1>
</div>
</div>
@endif
<div class="flex flex-col">
<div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
<div class="shadow overflow-hidden border-b border-gray-200 rounded-lg">
<table class="min-w-full divide-y divide-gray-200">
<thead>
<tr>
<th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
ID
</th>
<th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
Name
</th>
<th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
Email
</th>
<th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
Account Type
</th>
<th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
Creation
</th>
<th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@foreach($users as $key=>$user)
<tr>
<td class="px-6 py-4 whitespace-no-wrap">
<div class="text-sm leading-5 text-gray-900">
{{ $users->firstitem() + $key }}
</div>
</td>
<td class="px-6 py-4 whitespace-no-wrap">
<div class="text-sm leading-5 text-gray-900">
{{ $user->name }}
</div>
</td>
<td class="px-6 py-4 whitespace-no-wrap">
<div class="text-sm leading-5 text-gray-900">
{{ $user->email }}
</div>
</td>
<td class="px-6 py-4 whitespace-no-wrap">
<div class="text-sm leading-5 text-gray-900">
@foreach($user->Roles as $role)
{{ $role->name }}
@endforeach
</div>
</td>
<td class="px-6 py-4 whitespace-no-wrap">
<div class="text-sm leading-5 text-gray-900">
{{ $user->created_at->format('d-m-y') }}
</div>
</td>
<td class="px-6 py-4 whitespace-no-wrap text-right text-sm leading-5 font-medium">
<button wire:click="show({{ $user->id }})" class="text-indigo-600 hover:text-indigo-900">
View
</button>
<button wire:click="edit({{ $user->id }})" class="text-indigo-600 hover:text-indigo-900">
Edit
</button>
<button wire:click="delete({{ $user->id }})" class="text-indigo-600 hover:text-indigo-900">
Delete
</button>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="mt-4">
{{$users->links()}}
</div>
</div>
</div>
</div>
- create.blade.php
<div x-cloak x-show="open" class="fixed z-10 inset-0 overflow-y-auto">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div x-show="open" x-transition:enter="ease-out duration-300" x-transition:enter-start="opacity-0" x-transition:enter-end="opacity-100" x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100" x-transition:leave-end="opacity-0" class="fixed inset-0 transition-opacity">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen"></span>
<div x-show="open" x-transition:enter="ease-out duration-300" x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100" x-transition:leave="ease-in duration-200" x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100" x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" role="dialog" aria-modal="true" aria-labelledby="modal-headline">
<div class="shadow overflow-hidden sm:rounded-md">
<div class="px-4 py-5 bg-white sm:p-6">
<div class="grid grid-cols-6 gap-6">
<div class="col-span-6">
<label for="name" class="block text-sm font-medium leading-5 text-gray-700">Name</label>
<input wire:model="name" class="mt-1 form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5">
@error('name') <h1 class="text-sm font-medium leading-5 text-red-400 py-2">{{$message}}</h1>@enderror
</div>
<div class="col-span-6">
<label for="email" class="block text-sm font-medium leading-5 text-gray-700">Email</label>
<input wire:model="email" class="mt-1 form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5">
@error('email') <h1 class="text-sm font-medium leading-5 text-red-400 py-2">{{$message}}</h1>@enderror
</div>
<div class="col-span-6">
<label for="password" class="block text-sm font-medium leading-5 text-gray-700">Password</label>
<input wire:model="password" class="mt-1 form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5">
@error('password') <h1 class="text-sm font-medium leading-5 text-red-400 py-2">{{$message}}</h1>@enderror
</div>
<div class="col-span-6">
<label for="role" class="block text-sm font-medium leading-5 text-gray-700">Role</label>
<select wire:model="role" class="mt-1 form-select block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5">
<option value=""></option>
@foreach($roles as $role)
<option value="{{ $role->id }}">{{ $role->name }}</option>
@endforeach
@error('role') <h1 class="text-red-500">{{$message}}</h1>@enderror
</select>
@error('role') <h1 class="text-sm font-medium leading-5 text-red-400 py-2">{{$message}}</h1>@enderror
</div>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<span class="flex w-full rounded-md shadow-sm sm:ml-3 sm:w-auto">
<button wire:click.prevent="store()" type="button" class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-red-600 text-base leading-6 font-medium text-white shadow-sm hover:bg-red-500 focus:outline-none focus:border-red-700 focus:shadow-outline-red transition ease-in-out duration-150 sm:text-sm sm:leading-5">
Create
</button>
</span>
<span class="mt-3 flex w-full rounded-md shadow-sm sm:mt-0 sm:w-auto">
<button @click="open = false" type="button" class="inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-base leading-6 font-medium text-gray-700 shadow-sm hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue transition ease-in-out duration-150 sm:text-sm sm:leading-5">
Cancel
</button>
</span>
</div>
</div>
</div>
</div>
</div>
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 21 (5 by maintainers)
Way to go! Thanks for that.
Hello, people,
I have been facing similar issues.
Basically, the problem is that Livewire (through Alpine.js), is trying to remove a style attribute from the element, but the element does not have any style attribute originally.
Now, you can manually just add a style attribute to your component and avoid the error, appearing. BUT this would not probably resolve your issues in general.
Based on my recent experience, it is not a good idea to create a Livewire component for only a modal (or anything with a dynamic display property). Instead, try to “attach” the component to a more generic element that does not apply the x-show directive on it directly.
I hope it makes sense to some of you.
PS: Alternatively, you can try to use the @entangle directive of alpine, to synchronize the visualization or a component across Livewire and Alpine.js.