0

enter image description here

enter image description here

As you can see I am trying to make a list of categories, using ul/li on laravel livewire, the problem is that when I click on the "+" it transform to "-" as expected but retransform to "+", because I think DOM reloads.

controller:

<?php

namespace App\Http\Livewire\Product;

use App\Classes\Product\ShopifyCatList;
use Livewire\Component;

class ShopifyNewCategory extends Component
{
    public $categories, $html;

    private function getFirstCat()
    {
        $shopifyCatList = new ShopifyCatList();
        $this->categories = $shopifyCatList->getFirstCat();
    }

    public function addChildren($rank)
    {
        $shopifyCatList = new ShopifyCatList();
        $this->categories = $shopifyCatList->updateCategories($rank);
        $this->html = $shopifyCatList->updateHtml($this->html, $this->categories, $rank);
    }

    public function mount()
    {
        $this->getFirstCat();
        $this->html = '<li data-rank="' . $this->categories[0]['rank'] . '"><span class="sign" x-on:click="openList">+</span><span class="content">' . $this->categories[0]['name'] . '</span></li>';
    }

    public function render()
    {
        return view('livewire.product.shopify-new-category')->extends('layouts.app-livewire')->section('content');
    }
}

view:

@section('header')
    <div id="innerheader" style="display: flex;flex-direction: row;">
        <div style="flex:auto">
            <h1>Création nouvelle catégorie</h1>
        </div>
    </div>
@endsection
{{-- section content est mis dans le controller sinon form ne fonctionne pas correctement https://laracasts.com/discuss/channels/livewire/laravel-livewire-submitprevent-not-working-refreshing-page --}}
<form wire:submit.prevent="newCategory">
    @csrf
    <div class="form-group">
        <label for="name">Nom de la catégorie</label>
        <input type="text" class="form-control" id="name" name="name" placeholder="Nom de la catégorie"
            wire:model="name">
        @error('name')
            <span class="text-danger">{{ $message }}</span>
        @enderror
    </div>
    <div class="form-group">
        <label for="parent" id="parent">Catégorie parent: <b></b></label>
        <div x-data="categories" id="parent" class="border rounded bg-white overflow-auto" style="height:40vh;">
            <ul style="padding-left:2%">
                {!! $html !!}
            </ul>
        </div>
        @error('parent')
            <span class="text-danger">{{ $message }}</span>
        @enderror
    </div>
    <div class="d-flex justify-content-end">
        <button type="submit" class="btn btn-success mr-1" wire:click="updateValue('save')">Enregistrer</button>
        <button type="submit" class="btn btn-primary" wire:click="updateValue('saveRecreate')">Enregistrer et
            créer un autre</button>
    </div>
</form>

@push('styles')
    <style>
        .content ul {
            list-style: none;
        }

        span.sign {
            margin-right: 6px;
        }

        .content li {
            cursor: pointer;
        }

        .content li:hover {
            background-color: #39F856;
        }
    </style>
@endpush

<script>
    categories = () => {
        return {
            selected: '',
            labelNoticeSelected: $('label#parent b'),
            openList: (e) => {
                if (e.target.innerText === '+') {
                    e.target.innerText = '-';
                    @this.addChildren(e.target.parentNode.getAttribute('data-rank'));
                } else if (e.taget.innerText === '-') {
                    e.target.innerText = '+';
                    e.target.parentNode.parentNode.querySelector(
                            `li[data-rank='${e.target.parentNode.getAttribute('data-rank')}']+ul`).style
                        .display = 'none';
                }
            }
        }
    }
</script>

Here is all the code, I am also using alpinejs, when I click on the "+" I want to request db for children of the category I click on (that is ok) then I want it to transform "+" to "-" (that is not ok) so when I click on "-" it hides the children.

thanks for reading all of this and thanks to everyone trying to help.

2
  • 1
    make sure your view has a single root element. Commented Aug 16, 2022 at 18:27
  • that I can't, for some unknown reason if I add @push('scripts'), that's what I do on other pages, alpinejs doesn't work. Commented Aug 17, 2022 at 7:05

1 Answer 1

1

Either use a shared state between Livewire and Alpine (see docs) or wrap your button in a wire:ignore. (Potentially a wire:ignore.self if the DOM inside of the ignored div does require Livewire updates)

Sign up to request clarification or add additional context in comments.

5 Comments

I added wire:ignore.self to the sign span, it didn't work so I added it to the parent li but it didn't work neither, so I'm trying now to do something with @entangle but I can't figure out how to use it, not a livewire-alpinejs master, I have this: categories = () => { return { cats: @entangle('categories'), openList: (e) => { console.log(this.cats);} outputs undefined
I also tried with @this.get but didn't work
wire:ignore.self only ignores the DOM element it is attached to, not any children. @entangle only works if it's inside your Livewire component. As @Snapey has mentioned, ensure you have a single root element. Place your script tag inside the main root element.
I tried back with wire:ignore on the li and it worked, now I want to entangle a variable but I can't and as I said to @Snapey I can't place the script tag inside main root with @push('scripts') because alpinejs won't work. I need to entangle the variable in the script tags but I don't understand why I just can't, it returns undefined
You don't need to use @push. Scripts can be executed literally everywhere. Just move it inside the main root of your component and it should work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.