mirror of
https://github.com/ueberdosis/tiptap.git
synced 2024-12-15 02:59:01 +08:00
82625644be
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.
84 lines
2.2 KiB
Markdown
84 lines
2.2 KiB
Markdown
---
|
|
title: PHP WYSIWYG
|
|
tableOfContents: true
|
|
---
|
|
# PHP
|
|
|
|
## Introduction
|
|
You can use Tiptap with Laravel, Livewire, Inertia.js, [Alpine.js](/installation/alpine), [Tailwind CSS](/guide/styling#with-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](/api/utilities/tiptap-php). 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
|
|
```html
|
|
<!--
|
|
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
|
|
```html
|
|
<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
|
|
```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)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
```
|