Skip to content

Instantly share code, notes, and snippets.

@Gulivertx
Created July 16, 2024 16:27
Show Gist options
  • Save Gulivertx/0b9a594441396e0394f0879901127c94 to your computer and use it in GitHub Desktop.
Save Gulivertx/0b9a594441396e0394f0879901127c94 to your computer and use it in GitHub Desktop.
Quill.JS integration with Symfony project
{# File path in Symfony project : templates/form/layout_types.html.twig
Don't forget to add this file in symfony twig config inside section form_themes
#}
{%- block quill_textarea_row -%}
{%- set row_attr = row_attr|merge({ class: row_attr.class|default(row_class|default('flex-1')) }) -%}
{%- set widget_attr = {} -%}
{%- if help is not empty -%}
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
{%- endif -%}
<div
class="relative flex-1"
{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}
{{ stimulus_controller('forms--quill-textarea-type') }}
>
{{- form_label(form) -}}
{{- form_widget(form, widget_attr) -}}
<div {{ stimulus_target('forms--quill-textarea-type', 'editor') }}></div>
{{- form_errors(form) -}}
{{- form_help(form) -}}
</div>
{% endblock %}
<?php
// File path in Symfony project : src/Form/NotesType.php
namespace App\Form;
use App\Form\Type\QuillTextareaType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class NotesType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('personalNote', QuillTextareaType::class, [
'label' => false,
'required' => false,
])
;
}
...
}
// File path in Symfony project : assets/controllers/forms/quill-textarea-type_controller.ts
import {Controller} from '@hotwired/stimulus';
import Quill, {QuillOptions} from 'quill';
export default class extends Controller<HTMLDivElement> {
private editor: Quill;
static targets = [ "editor", "input" ]
declare readonly editorTarget: HTMLDivElement
declare readonly inputTarget: HTMLInputElement
connect() {
this.editor = new Quill(this.editorTarget, this.quillOption());
let value = this.inputTarget.value;
console.debug(value);
this.editor.setContents(this.editor.clipboard.convert({
html: value
}));
this.editor.on('text-change', this.onQuilTextChange);
}
disconnect() {
this.editor.off('text-change', this.onQuilTextChange);
}
private onQuilTextChange = () => {
this.inputTarget.value = this.editor.root.innerHTML;
}
private quillOption = (): QuillOptions => {
return {
modules: {
toolbar: [
[{ 'header': 1 }, { 'header': 2 }],
['bold', 'italic', 'underline', 'strike'],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'color': [] }, { 'background': [] }],
['link'],
['clean']
]
},
placeholder: 'Ajouter des notes personelles ici. Ces notes ne sont visible que par vous.',
readOnly: false,
theme: 'snow',
}
}
}
<?php
// File path in Symfony project : src/Form/Type/QuillTextareaType.php
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class QuillTextareaType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'attr' => [
'class' => 'input-hidden-accessible',
'data-forms--quill-textarea-type-target' => 'input',
],
]);
}
public function getParent(): string
{
return TextareaType::class;
}
public function getBlockPrefix(): string
{
return 'quill_textarea';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment