<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jordy</title>
    <description>The latest articles on DEV Community by Jordy (@jordypereira).</description>
    <link>https://dev.to/jordypereira</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F114560%2F4b814a6f-5ab7-4dcf-9a19-08b74ae10a2e.jpg</url>
      <title>DEV Community: Jordy</title>
      <link>https://dev.to/jordypereira</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jordypereira"/>
    <language>en</language>
    <item>
      <title>How to drag a tag into an editor. A simple solution after lots of iteration</title>
      <dc:creator>Jordy</dc:creator>
      <pubDate>Fri, 14 May 2021 15:27:34 +0000</pubDate>
      <link>https://dev.to/jordypereira/how-to-drag-a-tag-into-an-editor-a-simple-solution-after-lots-of-iteration-5bbc</link>
      <guid>https://dev.to/jordypereira/how-to-drag-a-tag-into-an-editor-a-simple-solution-after-lots-of-iteration-5bbc</guid>
      <description>&lt;p&gt;I made and wrote this article in 2019 for myself, but never had the nerve to publish it. This is a small story about creating a drag &amp;amp; drop editor in Vue.js&lt;/p&gt;

&lt;p&gt;If there's more interest I can try going more in-depth in the code and releasing a code sandbox example. &lt;/p&gt;

&lt;p&gt;TLDR;&lt;br&gt;
This is done using tiptap. Every single tag is a little uneditable tiptap editor. The tags inside are a custom Vue Tiptap node. So when you drag them into the real editable editors, they will recognize the node. We then render these nodes however we want.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Story
&lt;/h2&gt;

&lt;p&gt;We have this list with tags. The goal is to drag them into a full-fledged rich-text editor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Drag the tag around
&lt;/h2&gt;

&lt;p&gt;First, 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 complex layout.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Drop the tag
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Because the rich-text editor can't render Vue Components, he had to repeat the styling with a custom class.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Because the rich-text editor did not allow dropping tags inside of it, he made a separate component that gets switched when it detects a tag is being dragged.&lt;/p&gt;

&lt;p&gt;This separate component also had the logic to render a dropping indicator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rewrite 1: The project gets passed back to me
&lt;/h2&gt;

&lt;p&gt;Due to the lack of available time of my colleague, I get to finish the project.&lt;/p&gt;

&lt;p&gt;I first spent some time trying to decipher his code, which was quite plenty by now.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Almost giving up: This rich-text editor isn't made for this
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rewrite 2: Keep the dependencies down
&lt;/h2&gt;

&lt;p&gt;I just couldn't resist looking into other options. So I found &lt;a href="https://github.com/scrumpy/tiptap" rel="noopener noreferrer"&gt;tiptap, a renderless and extendable rich-text editor for Vue.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Going through the documentation, I saw something that looked exactly like the thing we needed: &lt;a href="https://www.tiptap.dev/guide/node-views/vue/#render-a-vue-component" rel="noopener noreferrer"&gt;Custom Vue components as nodes&lt;/a&gt;. This allowed me to make a custom &lt;code&gt;&amp;lt;tag&amp;gt;&lt;/code&gt; component that would get used inside of tiptap, which would render my real Tag component in vue.&lt;/p&gt;

&lt;p&gt;I decided to just give it a try. I might end up with something very clever.&lt;/p&gt;

&lt;p&gt;This dependency is quite new, so you can't just google what you want to find. So after a while of struggling to create a custom node, I managed to get it finished.&lt;/p&gt;

&lt;p&gt;Now I could at least re-use my Vue component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding it all together: Does this thing allow cross-editor dragging
&lt;/h2&gt;

&lt;p&gt;Then I started thinking. I was still switching between states. One editor to drop tags in, and one to edit your text.&lt;/p&gt;

&lt;p&gt;Apparently, tiptap allows you to make any Node draggable.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;And it seemed it could do that.&lt;/p&gt;

&lt;p&gt;4 weeks and a lot of code later, I ended up deleting most of it and replacing everything with tiptap editors.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
