SigalZ's avatar

Livewire Js script on nested component does not work

Using Laravel 10 Livewire 3.

I have a nested component where I need to use TinyMce.

Can't make it work.

After trying to find a solution on google, that's what I'm trying, but nothing works.

The parent component:

<?php

namespace App\Livewire\Admin\Coffee;

use App\Livewire\CrudComponent;
use Jantinnerezo\LivewireAlert\LivewireAlert;
use Livewire\Attributes\On;
use App\Livewire\Admin\Coffee\CoffeeForm;
use App\Models\Coffee;
use App\Models\Origin;
use App\Models\GreenBean;
use App\Models\RoastType;
use App\Models\Sticker;

class CoffeeComponent extends CrudComponent
{
    use LivewireAlert;

    public CoffeeForm $form;
    public $origins;
    public $beans;    
    public $roastTypes;
    public $stickers;
    public $myBody;
             
    public function mount()
    {
        $this->view = 'livewire.admin.coffee.coffee-component';
        $this->origins = Origin::orderBy('name')->get();
        $this->beans = GreenBean::orderBy('name')->get();        
        $this->roastTypes = RoastType::all();
        $this->stickers = Sticker::where('active', 1)->get();
        $this->myBody = "testing";
    }

    public function create()
    {
        $this->showForm = true;
        $this->formTitle = 'Create';
        $this->formAction = 'store';        
    }    
    
    public function store()
    {   
        $this->authorize('create', Coffee::class);     
        $this->form->store();

        $this->alert('success', 'Hurrah!', [
            'position' => 'center',
            'timer' => 3000,
            'toast' => false,
            'text' => 'Jobs Done! The coffee has been created.'
        ]);
        
        $this->dispatch('refreshTable');
    }

    #[On('edit')]
    public function edit($id)
    {
        $coffee = Coffee::findOrFail($id);
        $this->form->setCoffee($coffee);
        $this->formTitle = 'Edit';
        $this->formAction = 'update';
 
        $this->showForm = true;        
    }

    public function update()
    {
        $this->authorize('edit', Coffee::class);     

        $this->form->update();       
                
        $this->alert('success', 'Hurrah!', [
            'position' => 'center',
            'timer' => 3000,
            'toast' => false,
            'text' => 'Jobs Done! The coffee has been updated.'
        ]);
        
        $this->dispatch('refreshTable');
    }
}

The parent blade:

Under the scripts, I am trying to see if anything is being called on Livewire update etc.

No alert is being displayed when I click the 'Create' button.

<div>

@section('page-title', 'Coffees')

@section('breadcrumbs')
<li class="breadcrumb-item active">Coffees</li>
@stop

@if(!$showForm)
    <div class="mb-4">        
        @can('create coffees')
        <button wire:click="create" class="btn btn-primary">Create Coffee</button>        
        @endcan        
    </div>
@endif

@if($showForm)
     @include('livewire.admin.coffee.coffee-form')     
@endif

<x-tabs>
    <x-slot:tab_list> 
        <x-tab-list-item :active="$selectedTab == 0" selectedTab="0" name="On Website" href="active-coffees" />
        <x-tab-list-item :active="$selectedTab == 1" selectedTab="1" name="Not on Website" href="not-active-coffees" />                
    </x-slot:tab_list>
    
    <x-slot:tab_items>
        <div class="tab-pane fade @if($selectedTab == 0) active show @endif" id="active-coffees" role="tabpanel" aria-labelledby="active-boxes">
            <livewire:admin.coffee.coffee-table active="1" />
        </div>
        <div class="tab-pane fade @if($selectedTab == 1) active show @endif" id="not-active-coffees" role="tabpanel" aria-labelledby="not-active-boxes">
            <livewire:admin.coffee.coffee-table active="0" />
        </div>
    </x-slot:tab_items>
</x-tabs>

@push('js')    
    <script src="{{ asset('tinymce/tinymce.min.js') }}"></script>
    <script>
        tinymce.init({
            selector: 'textarea',
            height: '20rem'
        });         
   
        /////TESTING - No Alerts are being displayed when I click the 'Create' button
        
        /* This will be loaded when livewire update or load a new component inside master.blade.php */
        document.addEventListener('livewire:updated', function () {
                // Your JS for child component here.
                alert('child');
        });

        $wire.on('create', () => {
            alert('create');
        });

        document.addEventListener('livewire:init', () => {
            Livewire.on('create', (event) => {
                alert('create called');
            });
        });
    </script>
@endpush
</div>

The nested blade:

<div>

<x-card title="{{ $formTitle }} a Coffee">
    <x-livewire-form action="store">
        <div class="row">
            <div class="col-md-5">
                <div class="form-group required">
                    <label class="form-label">Origin</label>
                    <select class="form-control @error('form.originId') is-invalid @enderror" wire:model="form.originId">
                        <option value="">Select...</option>
                        @foreach($origins as $origin)
                            <option wire:key="{{ $origin->id }}" value="{{ $origin->id }}">{{ $origin->name }}</option>
                        @endforeach
                    </select>

                    @error(('form.originId'))
                        <x-display-error error="form.originId" />                           
                    @enderror
                </div>

                <div class="form-group required">
                    <label class="form-label" for="greenBean">Green Bean</label>
                    <select class="form-control @error('form.greenBeanId') is-invalid @enderror" id="greenBean" wire:model="form.greenBeanId">
                        <option value="">Select...</option>
                        @foreach($beans as $bean)
                            <option wire:key="{{ $bean->id }}" value="{{ $bean->id }}">{{ $bean->country->name }} / {{ $bean->name }}</option>
                        @endforeach
                    </select>
                    @error('form.greenBeanId')
                        <x-display-error error="form.greenBeanId" />
                    @enderror
                </div>

                <div class="form-group required">
                <label class="form-label">Roast Type</label>
                <select class="form-control  @error('form.roastTypeId') is-invalid @enderror" wire:model="form.roastTypeId">
                    <option value="">Select...</option>
                    @foreach($roastTypes as $type)
                        <option value="{{ $type->id }}" wire:key="{{ $type->id }}">{{ $type->name }}</option>
                    @endforeach
                </select>
                @error('form.roastTypeId')
                    <x-display-error error="form.roastTypeId" />
                @enderror
                </div>

                <div class="form-group required">
                    <label class="form-label" for="sticker">Sticker</label>
                    <select class="form-control @error('form.stickerId') @enderror" wire:model="form.stickerId" id="sticker">
                        <option value="">Select...</option>
                        @foreach($stickers as $sticker)
                            <option wire:key="{{ $sticker->id }}" value="{{ $sticker->id }}" wire:model="form.stickerId">{{ $sticker->name }}</option>
                        @endforeach
                    </select>
                    @error('form.stickerId')
                        <x-display-error error="form.stickerId" />
                    @enderror
                </div>

                <div class="form-group required">
                    <label class="form-label" for="name">Coffee Name</label>
                    <input type="text" id="name" class="form-control @error('form.name') is-invalid @enderror" wire:model="form.name">
                    <x-display-error error="form.name" />
                </div>

                <div class="form-group required" wire:ignore>
                    <label class="form-label" for="shortName">Coffee Short Name</label>                    
                    <input type="text" id="shortName" class="form-control @error('form.shortName') @enderror" wire:model="form.shorName">
                    <small class="form-text text-muted">Used for roasting reports</small>
                    @error('form.shortName')
                        <x-display-error error="form.shortName" />
                    @enderror
                </div>                
                
                <div class="form-group required">
                    <label for="price1kg">1kg Price</label>
                    <input type="number" class="form-control @error('form.price1kg') is-invalid @enderror" step=0.01 id="price1kg" wire:model="form.price1Kg">

                    @error('form.price1kg')
                        <x-display-error error="form.price1kg" />
                    @enderror
                </div>

                <div class="form-group required">
                    <label class="form-label" for="price250g">250g Price</label>
                    <input type="number" id="price250g" step=0.01 class="form-control @error('form.price250g') is-invalid @enderror">

                    @error('form.price250')
                        <x-display-error error="form.price250g" />
                    @enderror
                </div>

                <div class="form-group">
                    <label class="form-label" for="active">Display on Website</label>
                    <input type="checkbox" id="active" value="1" class="switch" wire:model="form.active">
                </div>

                <div class="form-group">
                    <label for="in-stock">In Stock</label>                    
                    <input type="checkbox" id="in-stock" wire:model="form.inStock" value="1" class="switch" checked>
                    <small class="form-text text-muted">If out of stock will show as Out of Stock on the website shop</small>
                </div>
            </div>
            
            <div class="col-md-7">
                <div class="form-group required" wire:ignore>
                    <label class="form-label" for="short-desc">Coffee Short Description</label>
                    <textarea class="form-control @error('form.shortDesc') is-invalid @enderror" wire:model.lazy="form.shortDesc" rows="4"></textarea>
                    <small class="form-text text-muted">Displays on shop for each coffee</small>
                    @error('form.shortDesc')
                        <x-display-error error="form.shortDesc" />
                    @enderror
                </div>

                <div class="form-group required">
                    <label class="form-label">Coffee Description</label>
                    <textarea class="form-control @error('form.coffeeDesc') is-invalid @enderror" wire:model="form.coffeeDesc" rows="7"></textarea>
                    <small class="form-text text-muted">Displays on Home page and on Shop for each coffee on Read more popup</small>
                    @error('form.coffeeDesc')
                        <x-display-error error="form.coffeeDesc" />
                    @enderror
                </div>
            </div>
        </div>
    </x-livewire-form>
</x-card>

</div>

Is there a way to make it work or should I just give up Livewire?

0 likes
6 replies
vincent15000's avatar

You say that it doesn't work.

What doesn't work ? Can you specify the problem, please ?

SigalZ's avatar

@vincent15000 TinyMCE does not change text box to text editor.

All the alerts I put for tests do not display.

1 like
vincent15000's avatar

@SigalZ I already had such a problem with ckeditor and I solved the problem by wrapping the textarea into a single div.

I don't know if it will solve your problem, but you can try.

SigalZ's avatar

@vincent15000 Thank you, but I think you miss the point. The javascripts are not being executed when calling the child component (pressing the 'create' button).

If I try to put the TinyMce in the parent component, it works fine.

1 like
vincent15000's avatar

@SigalZ Do you have any error in the console ?

Have you tried to push the JS script not in the parent component but in the child component ?

SigalZ's avatar

@vincent15000 There are no errors. And yes, I tried to push the js in the child component.

1 like

Please or to participate in this conversation.