We have this list with tags. Each of them is a tag component and receives a parent and child id. The goal is to drag them not just in any text, but into a full fledged rich-text editor.
4 weeks ago, I made it possible to drag the tag and release it in a box. This was not a rich-text editor yet, because those have their own lay-out.
When you click the tag, it creates a copy and you drag the copy. When you release the tag, it destroys the copy and appends the tag to the dropped element.
A colleague continued on this task. He focused on dragging the tag inside a rich-text editor. He did this by dividing the text into chunks and calculating which chunk you were hovering.
Because the rich-text editor can't render Vue Components, he had to repeat the styling with a custom class.
This was working quite well, except that he received errors for exceeding the stack trace. He was storing the dragged element inside the global store.
Now when you had the tag rendered and you wanted to delete it, it would treat it like regular text. So he made a function to detect if you pressed delete against a tag, and to delete the whole tag if that was the case.
Because the rich-text editor did not allow dropping of tags inside of it, he made a separate component that gets switched when it detects a tag is being dragged.
This separate component also had the logic to render a dropping indicator.
Due to lack of available time of my colleague, I get to finish the project.
I first spent some time trying to decipher his code, which was quite plenty by now.
If I wanted to work on this, I had to fix the things I didn't like about it. So I started with removing any elements stored in the global store.
I also wasn't a fan of transforming the text into chunks and detecting with javascript which classes you're bouncing into. I rather make something with the power that Vue provides us.
So I completely replaced the tag dropping logic. Now I stored an array of objects in the store, telling me if it contained a text or tag node.
Then I just looped over the array, rendering the text / tag and blocks in between. These blocks could detect mouseovers and would render the droppable placeholder.
Now I was still swapping between editors. The longer I kept thinking about future use-cases, such as detecting when you delete against a tag, making it not selectable, making the tag still draggable when it's rendered inside of the rich-text editor, the less I believed in completing this.
I just couldn't resist to look into other options. So I found tiptap, a renderless and extendable rich-text editor for Vue.js.
Going through the documentation, I saw something that looked exactly like the thing we needed: Custom Vue components as nodes. This allowed me to make a custom <tag>
component that would get used inside of tiptap, which would render my real Tag component in vue.
I decided to just give it a try. I might end up with something very clever.
This dependency is quite new, so you can't just google what you want to find. So after a while of struggling with creating my own custom node, I managed to get it finished.
Now I could at least re-use my Vue component.
Then I started thinking. I was still switching between states. One editor to drop tags in, and one to edit your text.
For some reason you could make any Node draggable by setting it to true.
If I could drag these tags between editors, I could just change the list with tags into mini non-readable editors, that render 1 tag, and drag those into my text fields.
And it seemed it could do that.
4 weeks and a lot of code later, I ended up deleting most of it and replacing it with tiptap editors.