Publier Il y a 2 mois

Intégrer Trix Editor dans un projet Symfony

Dans cet article, nous allons voir comment intégrer Trix Editor dans une application Symfony. Trix est un éditeur de texte WYSIWYG qui permet aux utilisateurs de formater facilement du contenu directement dans les formulaires.


Création du projet

symfony new trix-demo --webapp
cd trix-demo
symfony serve -d

Formulaire

// src/Form/ContentType.php
class ContentType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder->add('content', HiddenType::class);
    }
}

Installation et configuration de Trix editor

  • Installation
php bin/console importmap:req trix
  • Configuration de trix

Créer un Custom Element permet de réutiliser facilement l’éditeur partout dans l’application.

import Trix from 'trix'
import 'trix/dist/trix.min.css'

export default class Editor extends HTMLElement {

    connectedCallback() {
        this.render()
        this.configureTrix()
        this.setupEventListeners()
    }

    render() {
        this.innerHTML = `
            <div class="t-editor">
                <trix-editor input="post_form_content" class="trix-content"></trix-editor>
            </div>
        `
    }

    configureTrix () {
        Trix.config.blockAttributes.heading1 = {
            tagName: 'h2',
            terminal: true,
            breakOnReturn: true,
            group: false
        }
    }

    setupEventListeners () {
        this.addEventListener('trix-attachment-add', this.handleAttachmentAdd.bind(this))
        this.addEventListener('trix-attachment-remove', this.handleAttachmentRemove.bind(this))
    }

    handleAttachmentAdd (e) {
        const attachment = e.attachment

        if (e.attachment.file) {
            const setProgress = (progress) => {
                attachment.setUploadProgress(progress)
            }

            const setAttributes = (attributes) => {
                attachment.setAttributes(attributes)
            }

            if (attachment.file) {
                this.uploadFile(attachment.file, setProgress, setAttributes)
            }
        }
    }

    handleAttachmentRemove (e) {
        const url = '/trix/remove/' + e.attachment.getAttribute('url').split('/').pop()

        this.removeFile(url)
    }

    uploadFile (file, progressCallback, successCallback) {
        const formData = new FormData()
        formData.append("Content-Type", file.type)
        formData.append("file", file)

        const xhr = new XMLHttpRequest()
        xhr.open("POST", '/trix/upload', true)

        xhr.upload.addEventListener("progress", event => {
            const progress = event.loaded / event.total * 100;
            progressCallback(progress)
        })

        xhr.addEventListener("load", () => {
            if (xhr.status === 200) {
                const attributes = {
                    url: xhr.response,
                }
                successCallback(attributes)
            }
        })

        xhr.send(formData)
    }

    removeFile (url) {
        fetch(url)
            .then(r => console.log(r.json()))
            .catch(error => console.error(error))
    }
}
  • assets/app.js
import 'trix/dist/trix.min.css'
import { Editor } from './js/Editor.js'

customElements.define('t-editor', Editor)
  • content.html.twig
{{ form_start(form) }}
    <t-editor></t-editor>
    <button type="submit">Post</button>
{{ form_end(form) }}

Gestion des fichiers coté server

// src/Controller/TrixController.php

// Upload file
#[Route('/trix/upload', name: 'trix_upload', methods: ['POST'])]
public function upload(Request $request): Response
{
    $file = $request->files->get('file');
    $filename = uniqid().'.'.$file->guessExtension();
    $file->move($this->getParameter('kernel.project_dir').'/public/uploads/trix', $filename);

    return new Response('/uploads/trix/'.$filename);
}

// Remove file
#[Route('/trix/remove/{filename}', name: 'trix_remove', methods: ['POST', 'GET'])]
public function remove(string $filename): JsonResponse
{
    unlink('uploads/trix/'.$filename);
    return new JsonResponse(['status' => 'success']);
}

Et pour finir lancé le projet :

symfony serve -d
symfony console tailwind:build -w