tiptap/docs/installation/php.md
Peter Fox 82625644be
Update php.md (#3618)
Changes are based on reading this thread https://github.com/ueberdosis/tiptap/issues/1515#issuecomment-896477157

This example relies on AlpineJS still and doing causes the editor to be wrapped in an observable/reactive layer. Moving the editor out of the returned object means it doesn't become a proxy object; otherwise, `editor.commands.setContent(content, false)` will already trigger an error `Range Error: Applying a mismatched transaction` and not work.
2023-02-24 15:14:28 +01:00

2.2 KiB

title tableOfContents
PHP WYSIWYG true

PHP

Introduction

You can use Tiptap with Laravel, Livewire, Inertia.js, Alpine.js, Tailwind CSS, and even - yes you read that right - inside PHP.

Tiptap for PHP

We provide an official PHP package to work with Tiptap content. A PHP package to work with Tiptap content. You can transform Tiptap-compatible JSON to HTML, and the other way around, sanitize your content, or just modify it.

Laravel Livewire

my-livewire-component.blade.php

<!--
  In your livewire component you could add an
  autosave method to handle saving the content
  from the editor every 10 seconds if you wanted
-->
<x-editor
  wire:model="foo"
  wire:poll.10000ms="autosave"
></x-editor>

editor.blade.php

<div
  x-data="setupEditor(
    $wire.entangle('{{ $attributes->wire('model')->value() }}').defer
  )"
  x-init="() => init($refs.editor)"
  wire:ignore
  {{ $attributes->whereDoesntStartWith('wire:model') }}
>
  <div x-ref="editor"></div>
</div>

index.js

import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'

window.setupEditor = function (content) {
  let editor

  return {
    content: content,

    init(element) {
      editor = new Editor({
        element: element,
        extensions: [
          StarterKit,
        ],
        content: this.content,
        onUpdate: ({ editor }) => {
          this.content = editor.getHTML()
        }
      })

      this.$watch('content', (content) => {
        // If the new content matches TipTap's then we just skip.
        if (content === editor.getHTML()) return

        /*
          Otherwise, it means that a force external to TipTap
          is modifying the data on this Alpine component,
          which could be Livewire itself.
          In this case, we just need to update TipTap's
          content and we're good to do.
          For more information on the `setContent()` method, see:
            https://www.tiptap.dev/api/commands/set-content
        */
        editor.commands.setContent(content, false)
      })
    }
  }
}