Open benbucksch opened 9 months ago
Hey Ben,
I ran into something similar last night and created a solution for my specific need. I know it's not a complete solution, but in case it fits anyone else's problem.
Summary: I created two exported functions - one to insert text, used by a button. Another to bind the editor contents to another text field to mirror input. The latter I don't need/use, but just wrote real quick as a test.
In your TipTap editor component, create/export two functions outside of onMount:
// this will be called by the parent component in a button
export function insertText(text: string) {
editor?.commands.insertContent(text);
}
// this will be used by a textarea in the parent with on:input
// note: this will not account for formatting such as new lines
export function changeContent(text: string) {
editor?.commands.setContent(text);
}
Next, in your parent component, likely where you are calling the <Editor />
(or whatever you name it) component, create two variables:
$: changeText = '';
this is to bind/update the text
let component: Editor;
this is to bind to the actual component. Replace "Editor" with whatever your import name is. My import of the editor looks like this:
import Editor from '$lib/components/Editor.svelte';
If you aren't using TypeScript, you can probably just do let component;
Now, bind your component to use the exported functions.
<Editor bind:this={component} />
Create a textarea/input. I'll use it to get the text I want to insert in this example:
<textarea
rows="10"
bind:value={changeText}
></textarea>
In a button you can call insertText:
<button on:click={() => component.insertText(changeText)}>Insert Text</button>
And that's it.
If you want to bind the textarea to the Editor component, you can add this to your <textarea>
on:input={() => component.insertText(changeText)}
Note: as said before, it won't keep formatting like new lines the way it's currently written.
it won't keep formatting like new lines the way it's currently written.
Right. My first solution had the exact same problem, see initial description: "setContent(html)
again, which for some unknown reason strips the spaces."
I need the formatting and new lines, so this solution didn't work. Obviously, an HTML editor where I cannot get the content out nor not the formatting, is kind-of pointless. That's why I filed this bug here.
Try updating the function to the below. It looks to keep the new lines:
export function changeContent(text: string) {
editor?.commands.clearContent();
editor?.commands.insertContent(text);
}
update: further testing it even accepts html like <b>Bold</b>
in the plain textarea and reflects correctly in the editor. Still not a complete 2-way solution. Though if you need to bind 1-way it's a start.
Which packages did you experience the bug in?
tiptap/core in svelte
What Tiptap version are you using?
2.2.2
What’s the bug you are facing?
There is no official Svelte component for TipTap.
The documentation has only sample code for a Svelte component. However, that sample code has the HTML content hardcoded. Obviously, you'd make this a component property
html
. You'd also need to get the content that the user wrote out of it - that's the whole point of the editor. That's the bug here: This should be part of the sample code.If we try to add that functionality, that gives us:
However, this code has a bug: If the
html
property is changed by the parent component, then the changes do not apply. This is because the codecontent: html,
runsonMount()
only.This is needed not only when parents wants to specifically change the content, but mor importantly also when we simply change records / data. When we merely change record/data and only the property value changes, Svelte re-uses existing components and does not re-create them, so
onMount
doesn't run, sohtml
is not sent to the editor, so the changes are ignored, so the editor shows the wrong data of the previous record.Straight-forward fixes in standard Svelte way, like:
do not work, due to TipTap having its own mind. When I do this, I can no longer type spaces, or rather they are stripped, because
onUpdate
setshtml
, which then triggerssetContent(html)
again, which for some unknown reason strips the spaces.Given how Svelte re-uses components with new property data, this is the most basic usage of the TipTap editor in Svelte, and every developer will need to solve this. This should be part of the sample code Svelte component.
What browser are you using?
Firefox
Code example
https://tiptap.dev/docs/editor/installation/svelte
What did you expect to happen?
When
html
changes, the editor content reflects that new data.Anything to add? (optional)
No response
Did you update your dependencies?
Are you sponsoring us?