Bonjour,

Je suis actuellement sur la création d'un composant anonyme "contenteditable".

Ce que je veux

Je cherche à simuler l'utilisation de wire:model sur une div "contenteditable" , mais je n'arrive pas à le faire fonctionner.

J'utilise Laravel avec Livewire et AlpineJS.

Début de piste dont je me suis inspiré

Ce que j'ai fait

<div x-data="{ content: @entangle( $attributes->whereStartsWith('wire:model')->first() ) }" >
    <div x-on:blur="console.log(content)" contenteditable="true"
        {{ $attributes->merge(['class' => 'w-full px-3 py-2 outline-none focus:outline-none rounded-md shadow-sm focus:border'])->except('wire:model') }}
    >

    </div>
</div>

Utilisation sur page.blade.php

<x-contenteditable wire:model="variable" />

Ce que j'obtiens

Lors du runtime mon code compilé ressemble à ça

<div x-data="{ content: window.Livewire.find('qwI2wipKpA7Wv98zr8XA').entangle('model') }">
    <div x-on:blur="console.log(content)" contenteditable="true" class="w-full px-3 py-2 outline-none focus:outline-none rounded-md shadow-sm focus:border">ezezaezaea</div>
</div>

Le "Entangle" à l'air de fonctionner.

Lorsque je fais un console.log(content) j'obtiens un objet Proxy.

En remerciant par avance,
Adraknar.

3 réponses


Alors d'abord je réécrit tes codes proprement pour que ce soit lisible et ensuite je répondrais ^^:

<div x-data="{ content: @entangle( $attributes->whereStartsWith('wire:model')->first() ) }" >
    <div x-on:blur="console.log(content)" contenteditable="true"
        {{ $attributes->merge(['class' => 'w-full px-3 py-2 outline-none focus:outline-none rounded-md shadow-sm focus:border'])->except('wire:model') }}
    >

    </div>
</div>
<x-contenteditable wire:model="variable" />
<div x-data="{ content: window.Livewire.find('qwI2wipKpA7Wv98zr8XA').entangle('model') }">
    <div x-on:blur="console.log(content)" contenteditable="true" class="w-full px-3 py-2 outline-none focus:outline-none rounded-md shadow-sm focus:border">ezezaezaea</div>
</div>

alors deja ton component

<x-contenteditable wire:model="variable" />

C'est un component blade-x, pour injecter dans livewire il faut soit passer par un component livewire

<livewire:contenteditable wire:model="variable" />

(un component livewire n'est pas forcement une page, tu peux faire des simples components)

Soit mettre en variable et utiliser le wire dans le compo (pas sur que ça fonctionne):

<x-contenteditable variable="variable" />

contenteditable.blade.php

<input wire:model="{{ $variable }}" >
Adraknar
Auteur

Salut popotte et merci de ton retour !

Je me suis peut-être mal exprimé dans mon besoin.
Je reprends si tu me le permets.

Je suis actuellement en train de développer un projet avec Livewire et AlpineJS.
Je dois utiliser une div contenteditable pour accéder et modifier mes données.

Ce que je voudrais

J'aimerais partager l'état entre Livewire et AlpineJs en utilisant @entangle

Mon code

Mon code est en deux parties:
La première est une full-Page component ou j'enregistre un tableau de données (nommées $fruits ici). A ce tableau viendra être ajouter des sous-tableaux, présent dans un sous-composant fruit.
Je ne m'intéresse qu'à la partie lecture et modification du sous-composant pour le moment (pas de $emitUp" ou de communication enfant -> parent)

Ce sous-composant fruit contient un "form" qui me est supposé me permettre d'accéder et modifier mes données avec l'aide la directive @entangle et d'une div contenteditable.
Je suis obligé de passé par cette div contenteditable et non un champs de formulaire classique (input, textarea, select...)

App\Http\Livewire\ListFruit

<?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');
    }
}

resources/views/livewire/list-fruit.blade.php

<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>

App\Http\Livewire\Fruit

<?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');
    }
}

resources/views/livewire/fruit.blade.php


<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>

Le truc c'est que si j'avais un seul tableau sans sous-éléments, cela fonctionerait.
Example de données type :

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

J'ai également essayé d'accéder à mes données de cette manière là lors de mon passage dans la loop ( sans passer par la création d'un sous-composant) si ça peux aider.

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

Ce que j'obtiens

Dans la partie lecture ("livewire/fruit.blade.php") je lis un [object Object] proxy. J'ai essayé d'intérargir avec lui, mais le je n'ai pas assez de connaissance en JS. Et donc, lorsque j'essaie de modifier fruit.color ou fruit.type cela ne fonctionne pas. Je n'ai aucune de pourquoi.

Dans ma dernière tentative, j'ai essayé de séparer mes fruits dans un sous-composants me permettant de travailler sur un seul array, mais j'obtiens toujours cet objet.

Si toi ou quelqu'un d'autre pouvait m'aider, ce serait top ! ça va faire au moins 6 heures que je suis bloqué dessus ahah.

Adraknar.