Requesting help from a real human. Thank you.
Livewire + TipTap : How do I avoid live-update?
I'm trying to integrate TipTap editor with Livewire. So far, I was able to get it 'working' by copying code from blogs; and it's working. The problematic part? It updates live, sending requests too frequently. Instead, I'd like to send the editor content to backend only when the users clicks 'submit'. It looks easy, but I'm not able to get it to work.
<div>
<div>
<form wire:submit.prevent="save" class="border border-slate-300 rounded-lg p-4 space-y-4">
<div>
<flux:input wire:model="title" label="Title" description="The title of the discussion" />
</div>
<div>
<x-editor wire:model="body" />
</div>
<div>
<flux:button variant="primary">Primary</flux:button>
</div>
</form>
</div>
</div>
Livewire Class:
<?php
namespace App\Livewire\Community\Discussion;
use Livewire\Component;
class Create extends Component
{
public $title = "";
public $body = "";
public function save()
{
$body = $this->body;
// Will add logic to save the post
}
public function render()
{
return view('livewire.community.discussion.create');
}
}
Editor code: this is where I need help
<div>
<div
x-data="setupEditor(@entangle($attributes['wire:model']).live)"
x-init="() => init($refs.element)"
wire:ignore
{{ $attributes->whereDoesntStartWith('wire:model') }}
class="relative">
<!-- Editor Container -->
<div x-ref="element" class="bg-white min-h-48 mt-2 mb-6 p-2 border rounded-lg border-slate-300 overflow-y-auto focus:ring-2 focus:ring-slate-600 focus:border-transparent">
<template x-if="isLoaded()">
<div class="menu flex justify-start gap-x-3 mb-3 p-1 pb-3 border-b border-slate-200">
<!-- Heading Level 2 -->
<button @click="toggleHeading({ level: 2 })"
:class="{ 'is-active': isActive('heading', { level: 2 }, updatedAt) }"
class="border border-slate-400 rounded-md p-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none">
<path d="M3.5 5V19" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M13.5 5V19" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M20.5 19H16.5V18.6907C16.5 18.2521 16.5 18.0327 16.5865 17.8385C16.673 17.6443 16.836 17.4976 17.1621 17.2041L19.7671 14.8596C20.2336 14.4397 20.5 13.8416 20.5 13.214V13C20.5 11.8954 19.6046 11 18.5 11C17.3954 11 16.5 11.8954 16.5 13V13.4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M3.5 12L13.5 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</button>
<!-- Heading Level 3 -->
<button @click="toggleHeading({ level: 3 })"
:class="{ 'is-active': isActive('heading', { level: 3 }, updatedAt) }"
class="border border-slate-400 rounded-md p-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none">
<path d="M3.5 5V19" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M13.5 5V19" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M16.5 17C16.5 18.1046 17.3954 19 18.5 19C19.6046 19 20.5 18.1046 20.5 17C20.5 15.8954 19.6046 15 18.5 15C19.6046 15 20.5 14.1046 20.5 13C20.5 11.8954 19.6046 11 18.5 11C17.3954 11 16.5 11.8954 16.5 13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M3.5 12L13.5 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</button>
<!-- Bold -->
<button @click="toggleBold()"
:class="{ 'bg-slate-300' : isActive('bold', updatedAt) }"
class="border border-slate-400 rounded-md p-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 6C5 4.58579 5 3.87868 5.43934 3.43934C5.87868 3 6.58579 3 8 3H12.5789C15.0206 3 17 5.01472 17 7.5C17 9.98528 15.0206 12 12.5789 12H5V6Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M12.4286 12H13.6667C16.0599 12 18 14.0147 18 16.5C18 18.9853 16.0599 21 13.6667 21H8C6.58579 21 5.87868 21 5.43934 20.5607C5 20.1213 5 19.4142 5 18V12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</button>
<!-- Italic -->
<button @click="toggleItalic()"
:class="{ 'bg-slate-300' : isActive('italic', updatedAt) }"
class="border border-slate-400 rounded-md p-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none">
<path d="M12 4H19" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
<path d="M8 20L16 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
<path d="M5 20H12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
</svg>
</button>
<!-- Strike -->
<button @click="toggleStrike()"
:class="{ 'bg-slate-300' : isActive('strike', updatedAt) }"
class="border border-slate-400 rounded-md p-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none">
<path d="M4 12H20" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M17.5 7.66667C17.5 5.08934 15.0376 3 12 3C8.96243 3 6.5 5.08934 6.5 7.66667C6.5 8.15279 6.55336 8.59783 6.6668 9M6 16.3333C6 18.9107 8.68629 21 12 21C15.3137 21 18 19.6667 18 16.3333C18 13.9404 16.9693 12.5782 14.9079 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
</svg>
</button>
<!-- Link -->
<button @click="toggleLink()"
:class="{ 'bg-slate-300' : isActive('link', updatedAt) }"
class="border border-slate-400 rounded-md p-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none">
<path d="M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
<path d="M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
</svg>
</button>
|
<!-- Bullet List -->
<button @click="toggleBulletList()"
:class="{ 'bg-slate-300' : isActive('bulletList', updatedAt) }"
class="border border-slate-400 rounded-md p-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none">
<path d="M12 5.5L21 5.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
<path d="M12 12L21 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
<path d="M12 18.5L21 18.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
<path d="M8 5.5H3M4.04167 8L6.95833 3M6.95833 8L4.04167 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M8 18.5H3M4.04167 21L6.95833 16M6.95833 21L4.04167 16" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</button>
<!-- Ordered List -->
<button @click="toggleOrderedList()"
:class="{ 'bg-slate-300' : isActive('orderedList', updatedAt) }"
class="border border-slate-400 rounded-md p-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none">
<path d="M11 6L21 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
<path d="M11 12L21 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
<path d="M11 18L21 18" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
<path d="M3 15H4.5C4.77879 15 4.91819 15 5.03411 15.0231C5.51014 15.1177 5.88225 15.4899 5.97694 15.9659C6 16.0818 6 16.2212 6 16.5C6 16.7788 6 16.9182 5.97694 17.0341C5.88225 17.5101 5.51014 17.8823 5.03411 17.9769C4.91819 18 4.77879 18 4.5 18C4.22121 18 4.08181 18 3.96589 18.0231C3.48986 18.1177 3.11775 18.4899 3.02306 18.9659C3 19.0818 3 19.2212 3 19.5V20.4C3 20.6828 3 20.8243 3.08787 20.9121C3.17574 21 3.31716 21 3.6 21H6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
<path d="M3 3H4.2C4.36569 3 4.5 3.13431 4.5 3.3V9M4.5 9H3M4.5 9H6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</button>
<!-- Insert Image (example) -->
<button @click="triggerImageUploadDialog()"
class="border border-slate-400 rounded-md p-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="none">
<path d="M2.5 12C2.5 7.52166 2.5 5.28249 3.89124 3.89124C5.28249 2.5 7.52166 2.5 12 2.5C16.4783 2.5 18.7175 2.5 20.1088 3.89124C21.5 5.28249 21.5 7.52166 21.5 12C21.5 16.4783 21.5 18.7175 20.1088 20.1088C18.7175 21.5 16.4783 21.5 12 21.5C7.52166 21.5 5.28249 21.5 3.89124 20.1088C2.5 18.7175 2.5 16.4783 2.5 12Z" stroke="currentColor" stroke-width="1.5" />
<circle cx="16.5" cy="7.5" r="1.5" stroke="currentColor" stroke-width="1.5" />
<path d="M16 22C15.3805 19.7749 13.9345 17.7821 11.8765 16.3342C9.65761 14.7729 6.87163 13.9466 4.01569 14.0027C3.67658 14.0019 3.33776 14.0127 3 14.0351" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" />
<path d="M13 18C14.7015 16.6733 16.5345 15.9928 18.3862 16.0001C19.4362 15.999 20.4812 16.2216 21.5 16.6617" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round" />
</svg>
</button>
</div>
</template>
<!-- The actual editable area will be populated by TipTap -->
</div>
<!-- Dummy file upload input (if needed) -->
<input type="file" hidden id="imageUpload" @change="triggerUploadImage()">
</div>
</div>
The troubling part is:
x-data="setupEditor(@entangle($attributes['wire:model']).live)"
x-init="() => init($refs.element)"
wire:ignore
{{ $attributes->whereDoesntStartWith('wire:model') }}
I'm totally clueless about how to integrate the editor with livewire so that the contents are submitted only when I click 'submit' and not upon every update (live).
I'd really appreciate some help. Thank you!
Please or to participate in this conversation.