tiptap: AlpineJS v3 - Range Error: Applying a mismatched transaction
Description
I got Range Error: Applying a mismatched transaction when clicking on a menu button with AlpineJS v3.
CodeSandbox I created a CodeSandbox to help you debug the issue: https://codesandbox.io/s/tiptap-v2-alpinejs-v3-s5x2o
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 5
- Comments: 33 (5 by maintainers)
Commits related to this issue
- Update php.md 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 ... — committed to peterfox/tiptap by peterfox a year ago
- 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 ed... — committed to ueberdosis/tiptap by peterfox a year ago
- 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 ed... — committed to aliasliao/tiptap by peterfox a year ago
- Bdbch/list improvements v2 (#30) * v2.0.0-beta.205 * fix(extension-bubble-menu): don't debounce without valid selection (#3501) * refactor(extension-youtube): rename utility function name (#349... — committed to X-oss-byte/Tiptap.dev by X-oss-byte 9 months ago
- Update alpine.md with better info about proxy limitations The issue described in #1515 is now mentioned in the Alpine documentation so that readers understand why the example does not store the edito... — committed to justisr/tiptap by justisr 7 months ago
- Update alpine.md with better info about proxy limitations (#4678) The issue described in #1515 is now mentioned in the Alpine documentation so that readers understand why the example does not store t... — committed to ueberdosis/tiptap by justisr 7 months ago
- Update alpine.md with better info about proxy limitations (#4678) The issue described in #1515 is now mentioned in the Alpine documentation so that readers understand why the example does not store t... — committed to ueberdosis/tiptap by justisr 7 months ago
Wanted to share my solution for having the editor not reactive, but still have a reactive menu for Tiptap/Alpine v3: https://codesandbox.io/s/tiptap-with-alpine-js-v3-q4qbp
Thanks @EasterPeanut your solution is very helpful. But since I need to have multiple editor instances, so I ended up with this implementation:
The editor instances are saved to
windowas an object, the key is using the element id. Whenever I need the editor instance I only need to callthis.editor()method.If you add Alpine to the window scope you can use
Alpine.raw(editor)to unwrap the proxy and it should work.Just spotted this, and can hopefully point in the right direction, Alpine.js uses the reactive engine from Vue.js 3. Fixing it will be a very similar to what I did to get Vue3 working way back last year… https://github.com/ueberdosis/tiptap/issues/1166
From memory the trick with Vue was to use a ShallowRef() to hold the Editor object, this stops the reactive engine from trying to track all properties and methods within TipTap. (we then did a bunch of stuff to make the toolbars reactive but my memory gives up at that point)
It doesn’t look like Alpine exposes the
ShallowRef()api, but that will defiantly be the starting point to getting it working while having theEditorbe in yourx-data.(as others have mentioned having your editor object outside of
x-datais a good workaround, but obviously not ideal)Using the demos above as a reference, instead of using
this.editor, just usewindow.editor = new Editor(or name it however you like) and access it the same way. There’s no need to make it a reactive property, and that seems to be what’s breaking things here.That’s probably the more logical approach than my previous suggestion to unwrap the reactive parts on demand (with
Alpine.raw()).As some people described already this is a Proxy issue with Alpine. Alpine is using Proxy to have reactive objects - which is why this error is occuring.
Here you can see that a Proxy is sent to
applyTransaction- since this is not the correct way to apply a transaction prosemirror is throwing this error.Don’t know a solution for now, just so people know more about why and where this is happening.
Related to this error, I’m also experiencing a “Alpine Expression Error: editor is not defined” caused by a “Uncaught ReferenceError: editor is not defined”.
Test project: I followed the instructions in the doc and set up the example with Alpine 3. The basic editor worked BUT as soon as I added BubbleMenu or FloatingMenu it breaks again and Alpine can’t find the reference to the “editor” field anymore.
The placeholder extension worked though.
2 workarounds I found:
Thank you @EasterPeanut for the solution. Does anybody knows why in @EasterPeanut implementation buttons are not activated when are pressed but only when you press and type your first character (similarly when you deactivate)?
Updated:
Implementing the onTransaction function solved my issue:
That’s really smart! I’ll give it a shot.
Not sure if there’s a correct way to listen for a value changing with Alpine but this is how my buttons look:
Then in the editor:
I have
buttonsattribute in my Alpine component. With this attribute, not only I can give a different set of buttons for each editors but also I can use this to hold the buttons state and update the state by listening toonUpdateandonTransactionevents.In the html you can just loop the button collection and access the active state like:
@hanspagel the reactivity system in Alpine v3 is extracted from Vue’s reactivity system, so basically a trimmed down version only exposing the
reactivefunction, will need to take a look at Vue’s integration to see if I can be of any help@KevinBatdorf Thanks for the suggestion! I never knew about
Alpine.raw()@robertdrakedennis Here’s an example with the mentioned solution. https://codesandbox.io/s/tiptap-v2-alpinejs-v3-forked-2bbw8?file=/index.js
However,
Alpine.raw()doesn’t appear to be bindable for reactivity. I also am Alpine novice. Would be interested to know if anyone has any good suggestions as it would be kind of a hassle to create a separate attribute for every button we want to check activeness on.It appears to be definitely a proxy issue. I sort of got something working here by storing the editor object in a closure. https://codesandbox.io/s/tiptap-v2-alpinejs-v3-forked-6qxfs?file=/index.js
I don’t know why reactivity is not working but it’s a start and maybe this can point you in the right direction.
Hi, I think this is an Alpine issue. Downgrading to Alpine 2.8.2 works. It might have something to do with the fact that
this.editoris a Proxy object - though it’s just a theory.I don’t know if the
getUnobservedData()still works, but you could try to use it to get access to the actual editor object. https://codewithhugo.com/alpinejs-inspect-component-data-from-js/Hope this info helps 😄