0
votes

I'm currently developping a project with Livewire and AlpineJS.

I have to use a div with contenteditable set to "true" to access and modify my data model.

What I want

I would like to share the state between Livewire And Alpine using @entangle.

My code

My code is in two parts. The first-part rely on a full-Page component where I simply register an array of $fruits. The second, is a component containing a "form" allowing me to access and modify the data through @entangle and a div with contenteditable set to true.

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class ListFruit extends Component
{

    protected $listeners = ['addFruit'];

    public array $fruits = [];

    public function mount()
    {
        $this->addFruit();
    }

    public function addFruit()
    {
        $this->fruits[] = $this->makeBlankFruit();
    }



    public function makeBlankFruit(): array
    {
        return [
            'type' => '',
            'color' => ''
        ];
    }

      public function render()
    {
        return view('livewire.list-fruit');
    }
}

The views/livewire/list-fruit.blade.php file

<div  class="w-full container mx-auto">

    <h3 class="text-2xl font-sembibold">
          Fruits
    </h3>

    <div id="fruits">
       @foreach($fruits as $fruitIndex=> $fruit)

         <livewire:fruit :fruitIndex="$fruitIndex" :fruit="fruit" :wire:key="$fruitIndex" >

       @endforeach
    </div>

</div>

Fruit Component

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Fruit extends Component
{

    public array $fruit = [];

    public string $fruitIndex;

    public function render()
    {
        return view('livewire.fruit');
    }
}

views/livewire/fruit.blade.php file



<div x-data="{type: @entangle('fruit.type'), color: @entangle('fruit.color')}"
    x-init="console.log(type)"
>
    <div>
        <div x-on:blur="type = $event.target.innerHTML" contenteditable="true">{{ $fruit['type'] }}</div>
        <div x-on:blur="color = $event.target.innerHTML" contenteditable="true">{{ $fruit['color'] }}</div>
    </div>

    <div>
        $type @ Livewire: {{ $fruit['type'] }}
        $color @ Livewire: {{ $fruit['color']  }}
    </div>
    <div>
        type @ AlpineJS: <span x-text="type"></span>
        color @ AlpineJS: <span x-text="color"></span>
    </div>
</div>

If I had only one array with some properties in my main component, let's say :

 public array $fruit = [
  'type' => '',
  'color' => '',
 ];

I would be able to access them with my fruit.blade.php

I also tried to do something like this.

{type: @entangle('fruits.'. $fruitIndex.'.color'), color: @entangle('fruits.'. $fruitIndex.'.type')}

What I obtained

In my AlpineJs component I read an [object Object] proxy and when modifying my fruit.color or fruit.type property the livewire part isn't updated.

I don't know why. In my final attempt, I tried to separate my fruits into multiple sub-components allowing me to work on a single array.

I'm a looking at a dead end, so thank you in advance for your help. Tanuki