Adding Quill Editor to a Livewire-Alpine.js App
Published: 2020-06-13 19:12:50

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

- [Livewire](https://github.com/livewire/livewire) - Livewire is a full-stack framework for Laravel that takes the pain out of building dynamic UIs.
- [Alpine.js](https://github.com/alpinejs/alpine/) - Alpine.js is a rugged, minimal framework for composing JavaScript behavior in your markup.
- [Quill](https://github.com/quilljs/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.

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

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

---

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](https://laravel.com/docs/7.x/blade#stacks).

```html
<!-- 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
```

---

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.

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

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

---

`wire:model.debounce.3000ms="description"`. Given that we are now reproducing an `input` event, we can use Livewire`s data binding feature. Adding `wire: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.