Adding Quill Editor to a Livewire-Alpine.js App

eduarguz

Eduardo Guzmán

Posted on June 13, 2020

Adding Quill Editor to a Livewire-Alpine.js App

In case you are not familiar with the stack, this is a little tech reference:

  • Livewire - Livewire is a full-stack framework for Laravel that takes the pain out of building dynamic UIs.
  • Alpine.js - Alpine.js is a rugged, minimal framework for composing JavaScript behavior in your markup.
  • Quill - Quill is a modern WYSIWYG editor built for compatibility and extensibility.

Using third party libraries in Livewire is a very common use case. This time I faced the need to add a WYSIWYG editor and wanted to show how it can be achieved.

The very short response is shown in this snippet. Next, I will break down every piece.

This is how your Livewire component will look like.

<!-- livewire/edit-component.blade.php -->
@push('styles')
    <link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
@endpush

@push('scripts')
    <script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
@endpush

<div class="mt-2 bg-white" wire:ignore>
  <div
       x-data
       x-ref="quillEditor"
       x-init="
         quill = new Quill($refs.quillEditor, {theme: 'snow'});
         quill.on('text-change', function () {
           $dispatch('input', quill.root.innerHTML);
         });
       "
       wire:model.debounce.2000ms="description"
  >
    {!! $description !!}
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Now, let's break down the pieces that are working here.

In order to use Quill we need to import the library into our webpage. We use a CDN that will provide the css and the js that is required.
We are adding the <link> and <script> tags by using laravel blade stacks.

<!-- layouts/base.blade.php -->
<html>
  <head>
    @stack('styles')
  </head>
  <body>
    @stack('scripts')
  </body>
</html>

<!-- livewire/edit-component.blade.php -->
@push('styles')
  <link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
@endpush

@push('scripts')
  <script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
@endpush
Enter fullscreen mode Exit fullscreen mode

Next, add a <div> element in which we will be mounting Quill. Alpine.js will be used to mount the Editor into this element.

x-data will tell Alpine.js to declare a new component scope in this element, this way we can use other Alpine.js features.


x-ref=quillEditor will let us reference this DOM element in a very convenient way. We will be able to use $refs.quillEditor later when we need to reference this element.


x-init= will tell Apline.js to run an expression when this component is initialized. That is why we added the x-data on that component.

At this point we can already use Quill, we will initialize it and add its event handler.

First, we create a new instance of Quill and use the $ref.quillEditor to bind the editor into this Element.

Then, we use the same instance and add an event handler to it. The event handler will listen to the text-change event. When this event happens, we will fetch the HTML that has been added to the editor and by using Alpine.js's $dispatch feature, we will emit an input event in this component.

<div
  ...
  x-init="
    quill = new Quill($refs.quillEditor, {theme: 'snow'});

    quill.on('text-change', function () {
      $dispatch('input', quill.root.innerHTML);
    });
  "
>...</div>
Enter fullscreen mode Exit fullscreen mode

wire:model.debounce.3000ms="description". Given that we are now reproducing an input event, we can use Livewires data binding feature. Addingwire:model="description"` will bind the value of the Quill editor right into our Livewire component. This way we can have this data in our Laravel app.

Adding debounce.2000ms to the data binding will debounce these many input events and update the value of the property after 2000 ms.


wire:ignore Adding this to a parent element will tell Livewire to skip DOM-diffing for this element, this is useful because Quill adds elements that Livewire does not know from the original HTML. This will prevent a small page flicker when re-rendering Livewire components.

Closing

That's it, very easy and right into your HTML Markup.

The same approach will work with many other third party libraries.

Enjoy the Livewire - AlpineJs Stack.

💖 💪 🙅 🚩
eduarguz
Eduardo Guzmán

Posted on June 13, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related