{"id":4069,"date":"2022-02-24T15:17:55","date_gmt":"2022-02-24T15:17:55","guid":{"rendered":"https:\/\/ionicframework.com\/blog\/?p=4069"},"modified":"2023-01-21T00:30:52","modified_gmt":"2023-01-21T05:30:52","slug":"building-with-stencil-drag-and-drop-components","status":"publish","type":"post","link":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components","title":{"rendered":"Building with Stencil: Drag-and-Drop Components"},"content":{"rendered":"<p>Drag-and-drop functionality is growing more and more popular on the web, and with good reason. Drag-and-drop features are both intuitive and provide a really enjoyable user experience. In this tutorial, we\u2019re going to take a look at how you can build your very own drag-and-drop components using <a href=\"https:\/\/stenciljs.com\/\">Stencil<\/a>. For this tutorial, we\u2019re going to be building a Kanban board, but the principles can be used to build any kind of drag-and-drop experience. Here\u2019s what our final product will look like.<\/p>\n<p><!--more--><\/p>\n<p><video width=\"400\" controls=\"\" autoplay=\"\"><source src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/02\/Kanban-Demo.mov\" type=\"video\/mp4\"><\/video><\/p>\n<p>You can find all of the code for this tutorial on the <a href=\"https:\/\/github.com\/a-giuliano\/sortable\">Stencil Sortable Github repo here<\/a>. If you prefer to watch a video tutorial, I recently created a video where I walk through this entire process. Check it out!<\/p>\n<div class=\"video-container\">\n              <iframe data-src=\"https:\/\/www.youtube.com\/embed\/NVjYrGcThck\"frameborder=\"0\" allowfullscreen src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" class=\"lazyload\" data-load-mode=\"1\"><\/iframe>\n            <\/div>\n<h2>Sortable JS<\/h2>\n<p>Building a drag-and-drop experience is notoriously difficult; so, to help us out, we\u2019re going to be using a JavaScript library called <a href=\"https:\/\/github.com\/SortableJS\/Sortable\">Sortable JS<\/a>. Sortable is going to help simplify our drag-and-drop logic.<\/p>\n<blockquote><p>\n  NOTE: This tutorial assumes that you have a <a href=\"https:\/\/stenciljs.com\/docs\/getting-started\">fundamental understanding of building components in Stencil<\/a>. This tutorial will focus on the aspects related to implementing the drag-and-drop functionality.<\/p><\/blockquote>\n<h2>Getting Started<\/h2>\n<p>As always, I want to start with an idea of what our component is going to look like in an html file. In this tutorial, we\u2019re going to build two elements. We\u2019ll have a <code>drag-and-drop-container<\/code> with a <code>container-title<\/code> and then, as children of that container, we\u2019ll have some <code>draggable-item<\/code>s. The <code>draggable-item<\/code> component can really be anything we want, but for this tutorial I\u2019m going to make it a task on a kanban board. To do that, I\u2019m going to provide a <code>task-title<\/code>, <code>due-date<\/code>, and <code>assignee-avatar<\/code>. This scaffold will now serve as our guide as we build out these components.<\/p>\n<pre><code class=\"language-html\">&lt;drag-and-drop-container container-title=&quot;Backlog&quot;&gt;\n  &lt;draggable-item task-title=&quot;Edit tutorial video&quot; due-date=&quot;12\/25\/21&quot; assignee-avatar=&quot;https:\/\/avatars.dicebear.com\/api\/micah\/example0.svg&quot;&gt;&lt;\/draggable-item&gt;\n  &lt;draggable-item task-title=&quot;Publish video on Youtube&quot; due-date=&quot;12\/25\/21&quot; assignee-avatar=&quot;https:\/\/avatars.dicebear.com\/api\/micah\/example1.svg&quot;&gt;&lt;\/draggable-item&gt;\n&lt;\/drag-and-drop-container&gt;\n<\/code><\/pre>\n<h2>Creating the Draggable Item<\/h2>\n<p>With that in mind, let\u2019s go ahead and create our <code>draggable-item<\/code> component. This component is going to be largely presentational. We\u2019ll take in our properties as strings, and then render them in an organized way. Let\u2019s take a look at it.<\/p>\n<pre><code class=\"language-jsx\">@Component({\n  tag: &#039;draggable-item&#039;,\n  styleUrl: &#039;draggable-item.css&#039;,\n  shadow: true,\n})\nexport class DraggableItem {\n  @Prop() taskTitle: string;\n  @Prop() dueDate: string;\n  @Prop() assigneeAvatar: string;\n\n  render() {\n    return (\n      &lt;Host&gt;\n        &lt;h1&gt;{this.taskTitle}&lt;\/h1&gt;\n        &lt;div class=&quot;bottom-row&quot;&gt;\n          &lt;ion-icon size=&quot;32&quot; name=&quot;calendar-outline&quot;&gt;&lt;\/ion-icon&gt;\n          &lt;p&gt;{this.dueDate}&lt;\/p&gt;\n          &lt;img src={this.assigneeAvatar} \/&gt;\n        &lt;\/div&gt;\n      &lt;\/Host&gt;\n    );\n  }\n}\n<\/code><\/pre>\n<p>Let\u2019s add some CSS as well in our <code>draggable-item.css<\/code> file.<\/p>\n<pre><code class=\"language-css\">:host {\n  display: block;\n  min-width: 300px;\n  padding: 8px;\n  border-radius: 8px;\n  margin-bottom: 8px;\n  color: #03060b;\n  background: white;\n}\n\n:host(:hover) {\n  cursor: pointer;\n  outline: 1px solid #03060b;\n}\n\nh1 {\n  font-size: 1.375rem;\n  margin: 0;\n}\n\np {\n  font-size: 1rem;\n  margin: 0;\n}\n\n.bottom-row {\n  display: flex;\n  align-items: flex-end;\n  gap: 8px;\n}\n\nion-icon {\n  font-size: 1rem;\n}\n\nimg {\n  height: 32px;\n  width: 32px;\n  padding: 2px;\n  border-radius: 50%;\n  border: 1px solid black;\n  margin-left: auto;\n}\n<\/code><\/pre>\n<p>Our <code>draggable-item<\/code> is composed of only markup and styles because all of our drag-and-drop logic is going to go in our <code>drag-and-drop-container<\/code> component. By putting all of our business logic there, we give ourselves a very flexible setup where any component can become a draggable item by just being placed within a <code>drag-and-drop-container<\/code>.<\/p>\n<h2>Creating the Drag-and-Drop Container<\/h2>\n<p>Let\u2019s go ahead and start building our <code>drag-and-drop-container<\/code> by creating a new Stencil component. First we\u2019ll take in a <code>Prop<\/code> for our <code>containerTitle<\/code> and display it in our render method.<\/p>\n<pre><code class=\"language-JSX\">@Component({\n  tag: &#039;drag-and-drop-container&#039;,\n  styleUrl: &#039;drag-and-drop-container.css&#039;,\n  shadow: true,\n})\nexport class DragAndDropContainer {\n  @Prop() containerTitle: string;\n\n  render() {\n    return (\n      &lt;Host&gt;\n        &lt;h1&gt;{this.containerTitle}&lt;\/h1&gt;\n      &lt;\/Host&gt;\n    );\n  }\n}\n<\/code><\/pre>\n<p>Next we\u2019ll add some styles in our <code>drag-and-drop-container.css<\/code> file.<\/p>\n<pre><code class=\"language-css\">:host {\n  display: flex;\n  flex-direction: column;\n  color: #03060b;\n  background: rgb(230, 230, 230);\n  padding: 8px;\n  border-radius: 8px;\n}\n\nh1 {\n  margin: 0;\n  margin-bottom: 16px;\n}\n<\/code><\/pre>\n<p>Turning back to our component, we can now start working towards our drag-and-drop functionality. The first thing we\u2019ll want to do is create an area within our container where elements can be dragged to and from. I\u2019m going to call this the \u201cdraggable area\u201d. We can do that by adding a <code>div<\/code> to our component that will serve as this area. We\u2019ll put our <code>slot<\/code> element within this <code>div<\/code> so all of the container\u2019s children will be included in the draggable area.<\/p>\n<pre><code class=\"language-JSX\">render() {\n  return (\n    &lt;Host&gt;\n      &lt;h1&gt;{this.containerTitle}&lt;\/h1&gt;\n      &lt;div&gt;\n        &lt;slot&gt;&lt;\/slot&gt;\n      &lt;\/div&gt;\n    &lt;\/Host&gt;\n  );\n}\n<\/code><\/pre>\n<h2>Using Sortable<\/h2>\n<p>Next we\u2019ll use Sortable to add the drag-and-drop functionality to our draggable area. To do that, Sortable is going to need a reference to the draggable area. To create a reference, we\u2019ll create a private class member called <code>container<\/code> and assign it to our <code>div<\/code> with the <code>ref<\/code> attribute.<\/p>\n<pre><code class=\"language-JSX\">export class DragAndDropContainer {\n  @Prop() containerTitle: string;\n\n  private container: HTMLElement;\n\n  render() {\n    return (\n      &lt;Host&gt;\n        &lt;h1&gt;{this.containerTitle}&lt;\/h1&gt;\n        &lt;div ref={el =&gt; (this.container = el as HTMLElement)}&gt;\n          &lt;slot&gt;&lt;\/slot&gt;\n        &lt;\/div&gt;\n      &lt;\/Host&gt;\n    );\n  }\n}\n<\/code><\/pre>\n<p>Speaking of Sortable, we\u2019re now ready to add it to our project. Let\u2019s install Sortable via npm.<\/p>\n<pre><code class=\"language-bash\">npm install sortablejs\n<\/code><\/pre>\n<p>We\u2019ll also need to add the Sortable script tag in the <code>head<\/code> of our <code>index.html<\/code> file.<\/p>\n<pre><code class=\"language-html\">&lt;script type=&quot;module&quot; src=&quot;\/build\/sortable.esm.js&quot;&gt;&lt;\/script&gt;\n<\/code><\/pre>\n<p>Moving back to our <code>drag-and-drop-container<\/code> component, we can import Sortable at the top of our file.<\/p>\n<pre><code class=\"language-js\">import { Component, Host, h, Prop } from &#039;@stencil\/core&#039;;\nimport Sortable from &#039;sortablejs&#039;;\n<\/code><\/pre>\n<p>With that in place, we can make use of the <code>Sortable.create<\/code> method.<\/p>\n<pre><code class=\"language-js\">private container: HTMLElement;\n\ncomponentDidLoad() {\n  Sortable.create(this.container, {\n    animation: 150,\n  });\n}\n<\/code><\/pre>\n<p><code>Sortable.create<\/code> takes two parameters. The first parameter is the element we want to turn into a draggable area, so we\u2019ll pass the reference to our container. The second parameter allows us to specify <a href=\"https:\/\/github.com\/SortableJS\/Sortable#options\">different options<\/a> that we\u2019ll revisit later, but for now we\u2019ll just set the animation speed to 150ms.<\/p>\n<p>Now you may be wondering why we put this block in the <code>componentDidLoad<\/code> method. The reason is that in order for us to use our container reference, we have to wait until it&#8217;s assigned in our <code>render<\/code> method. Once it\u2019s assigned, then we can make use of it. So we put this in <code>componentDidLoad<\/code> because it runs after our <code>render<\/code> method in the <a href=\"https:\/\/stenciljs.com\/docs\/component-lifecycle\">component lifecycle<\/a>.<\/p>\n<h2>Working with the Shadow DOM<\/h2>\n<p>If you\u2019re coding along, you might notice that our drag-and-drop component doesn\u2019t work yet, even though all of the pieces seem to be in place. This is a common sticking point for many developers and it has to do with our use of the <a href=\"https:\/\/stenciljs.com\/docs\/styling\">shadow DOM<\/a>. The shadow DOM provides both style and DOM encapsulation. Because of that, Sortable isn\u2019t able to reach in and manipulate the DOM nodes in our component. Fortunately, we can make our component a bit more flexible by changing <code>shadow<\/code> to <code>scoped<\/code> in the component decorator.<\/p>\n<pre><code class=\"language-js\">@Component({\n  tag: &#039;drag-and-drop-container&#039;,\n  styleUrl: &#039;drag-and-drop-container.css&#039;,\n  scoped: true,\n})\n<\/code><\/pre>\n<p>In doing this, we still get style encapsulation, and now Sortable is able to manipulate the elements within our component.<\/p>\n<h2>Drag Elements Across Containers<\/h2>\n<p>So now our drag-and-drop component works in isolation, but what if we want to drag elements between different containers? Fortunately, Sortable has a solution for that. We can do this using a property called <code>group<\/code> and then setting the <code>group<\/code> option in the <code>Sortable.create<\/code> method.<\/p>\n<pre><code class=\"language-ts\">export class DragAndDropContainer {\n  @Prop() containerTitle: string;\n  @Prop() group: string;\n\n  private container: HTMLElement;\n\n  componentDidLoad() {\n    Sortable.create(this.container, {\n      animation: 150,\n      group: this.group,\n      ghostClass: &#039;ghost&#039;,\n    });\n  }\n<\/code><\/pre>\n<p>Now, <code>drag-and-drop-container<\/code>s that have the same <code>group<\/code> will be able to share elements. Let\u2019s turn back to our <code>index.html<\/code> file to see what this looks like in practice.<\/p>\n<pre><code class=\"language-html\">&lt;drag-and-drop-container container-title=&quot;Backlog&quot; group=&quot;kanban&quot;&gt;\n  &lt;draggable-item task-title=&quot;Edit tutorial video&quot; due-date=&quot;12\/25\/21&quot; assignee-avatar=&quot;https:\/\/avatars.dicebear.com\/api\/micah\/example0.svg&quot;&gt;&lt;\/draggable-item&gt;\n  &lt;draggable-item task-title=&quot;Publish video on Youtube&quot; due-date=&quot;12\/25\/21&quot; assignee-avatar=&quot;https:\/\/avatars.dicebear.com\/api\/micah\/example1.svg&quot;&gt;&lt;\/draggable-item&gt;\n&lt;\/drag-and-drop-container&gt;\n\n&lt;drag-and-drop-container container-title=&quot;In Progress&quot; group=&quot;kanban&quot;&gt;\n  &lt;draggable-item task-title=&quot;Film tutorial video&quot; due-date=&quot;12\/25\/21&quot; assignee-avatar=&quot;https:\/\/avatars.dicebear.com\/api\/micah\/example2.svg&quot;&gt;&lt;\/draggable-item&gt;\n  &lt;draggable-item task-title=&quot;Push code to Github&quot; due-date=&quot;12\/25\/21&quot; assignee-avatar=&quot;https:\/\/avatars.dicebear.com\/api\/micah\/example3.svg&quot;&gt;&lt;\/draggable-item&gt;\n&lt;\/drag-and-drop-container&gt;\n\n&lt;drag-and-drop-container container-title=&quot;Done&quot; group=&quot;kanban&quot;&gt;\n  &lt;draggable-item task-title=&quot;Create code demo&quot; due-date=&quot;12\/25\/21&quot; assignee-avatar=&quot;https:\/\/avatars.dicebear.com\/api\/micah\/example4.svg&quot;&gt;&lt;\/draggable-item&gt;\n  &lt;draggable-item task-title=&quot;Write video script&quot; due-date=&quot;12\/25\/21&quot; assignee-avatar=&quot;https:\/\/avatars.dicebear.com\/api\/micah\/example5.svg&quot;&gt;&lt;\/draggable-item&gt;\n&lt;\/drag-and-drop-container&gt;\n<\/code><\/pre>\n<p>Here, I\u2019ve created three <code>drag-and-drop-container<\/code>s, each with two <code>draggable-item<\/code> children. You\u2019ll notice that each <code>drag-and-container<\/code> has the <code>group<\/code> attribute set to \u201ckanban.\u201d Because they all share the same group, we\u2019ll be able to drag and drop elements between these containers.<\/p>\n<h2>One Final Flourish<\/h2>\n<p>To add a little style to our drag-and-drop components, we can take advantage of the <code>ghostClass<\/code> option of <code>Sortable.create<\/code>. This option allows us to provide a class name that we can use to style the space where a draggable element will be dropped.<\/p>\n<pre><code class=\"language-js\">componentDidLoad() {\n  Sortable.create(this.container, {\n    animation: 150,\n    group: this.group,\n    ghostClass: &#039;ghost&#039;,\n  });\n}\n<\/code><\/pre>\n<p>Now we can go into our <code>draggable-item.css<\/code> file and add a style to be applied whenever the ghost class is given to our item. Sortable adds this class to an item any time it is dragged.<\/p>\n<pre><code class=\"language-css\">:host(.ghost) {\n  background: rgba(76, 72, 255, 0.75);\n}\n<\/code><\/pre>\n<h2>Conclusion<\/h2>\n<p>And with that, our drag-and-drop component is complete! To me, the most exciting aspect of this is that we have barely scratched the surface of what we can do with Stencil and Sortable. So <a href=\"https:\/\/github.com\/a-giuliano\/sortable\">pull down the code from Github<\/a>, take a look at <a href=\"https:\/\/github.com\/SortableJS\/Sortable\">Sortable\u2019s documentation<\/a>, and go build something amazing. Happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Drag-and-drop functionality is growing more and more popular on the web, and with good reason. Drag-and-drop features are both intuitive and provide a really enjoyable user experience. In this tutorial, we\u2019re going to take a look at how you can build your very own drag-and-drop components using Stencil. For this tutorial, we\u2019re going to be [&hellip;]<\/p>\n","protected":false},"author":87,"featured_media":4070,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"publish_to_discourse":"1","publish_post_category":"21","wpdc_auto_publish_overridden":"","wpdc_topic_tags":"","wpdc_pin_topic":"","wpdc_pin_until":"","discourse_post_id":"542989","discourse_permalink":"https:\/\/forum.ionicframework.com\/t\/building-with-stencil-drag-and-drop-components\/220843","wpdc_publishing_response":"","wpdc_publishing_error":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1,223,124],"tags":[140,76,82],"class_list":["post-4069","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-all","category-stencil","category-tutorials","tag-design-systems","tag-stencil","tag-web-components"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.0 (Yoast SEO v23.0) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Building with Stencil: Drag-and-Drop Components - Ionic Blog<\/title>\n<meta name=\"description\" content=\"In this tutorial, we\u2019re going to take a look at how you can build your very own drag-and-drop components using Stencil.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building with Stencil: Drag-and-Drop Components\" \/>\n<meta property=\"og:description\" content=\"In this tutorial, we\u2019re going to take a look at how you can build your very own drag-and-drop components using Stencil.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components\" \/>\n<meta property=\"og:site_name\" content=\"Ionic Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-02-24T15:17:55+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-01-21T05:30:52+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/02\/dragndrop-feature-image.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"880\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Anthony Giuliano\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@a__giuliano\" \/>\n<meta name=\"twitter:site\" content=\"@ionicframework\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Anthony Giuliano\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#article\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components\"},\"author\":{\"name\":\"Anthony Giuliano\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/a3190e4d49187220d0c720f2ceab9b58\"},\"headline\":\"Building with Stencil: Drag-and-Drop Components\",\"datePublished\":\"2022-02-24T15:17:55+00:00\",\"dateModified\":\"2023-01-21T05:30:52+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components\"},\"wordCount\":1120,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/02\/dragndrop-feature-image.png\",\"keywords\":[\"Design Systems\",\"stencil\",\"web components\"],\"articleSection\":[\"All\",\"Stencil\",\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components\",\"url\":\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components\",\"name\":\"Building with Stencil: Drag-and-Drop Components - Ionic Blog\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#primaryimage\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/02\/dragndrop-feature-image.png\",\"datePublished\":\"2022-02-24T15:17:55+00:00\",\"dateModified\":\"2023-01-21T05:30:52+00:00\",\"description\":\"In this tutorial, we\u2019re going to take a look at how you can build your very own drag-and-drop components using Stencil.\",\"breadcrumb\":{\"@id\":\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#primaryimage\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/02\/dragndrop-feature-image.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/02\/dragndrop-feature-image.png\",\"width\":1600,\"height\":880},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/ionic.io\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Building with Stencil: Drag-and-Drop Components\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ionic.io\/blog\/#website\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"name\":\"ionic.io\/blog\",\"description\":\"Build amazing native and progressive web apps with the web\",\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/ionic.io\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/ionic.io\/blog\/#organization\",\"name\":\"Ionic\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"width\":1920,\"height\":854,\"caption\":\"Ionic\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/ionicframework\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/a3190e4d49187220d0c720f2ceab9b58\",\"name\":\"Anthony Giuliano\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/10\/anthony-giuliano-profile-cropped-150x150.jpeg\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/10\/anthony-giuliano-profile-cropped-150x150.jpeg\",\"caption\":\"Anthony Giuliano\"},\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/anthonygiuliano1\/\",\"https:\/\/x.com\/a__giuliano\"],\"url\":\"https:\/\/ionic.io\/blog\/author\/anthonyionic-io\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Building with Stencil: Drag-and-Drop Components - Ionic Blog","description":"In this tutorial, we\u2019re going to take a look at how you can build your very own drag-and-drop components using Stencil.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components","og_locale":"en_US","og_type":"article","og_title":"Building with Stencil: Drag-and-Drop Components","og_description":"In this tutorial, we\u2019re going to take a look at how you can build your very own drag-and-drop components using Stencil.","og_url":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components","og_site_name":"Ionic Blog","article_published_time":"2022-02-24T15:17:55+00:00","article_modified_time":"2023-01-21T05:30:52+00:00","og_image":[{"width":1600,"height":880,"url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/02\/dragndrop-feature-image.png","type":"image\/png"}],"author":"Anthony Giuliano","twitter_card":"summary_large_image","twitter_creator":"@a__giuliano","twitter_site":"@ionicframework","twitter_misc":{"Written by":"Anthony Giuliano","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#article","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components"},"author":{"name":"Anthony Giuliano","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/a3190e4d49187220d0c720f2ceab9b58"},"headline":"Building with Stencil: Drag-and-Drop Components","datePublished":"2022-02-24T15:17:55+00:00","dateModified":"2023-01-21T05:30:52+00:00","mainEntityOfPage":{"@id":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components"},"wordCount":1120,"commentCount":0,"publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"image":{"@id":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/02\/dragndrop-feature-image.png","keywords":["Design Systems","stencil","web components"],"articleSection":["All","Stencil","Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#respond"]}]},{"@type":"WebPage","@id":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components","url":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components","name":"Building with Stencil: Drag-and-Drop Components - Ionic Blog","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#primaryimage"},"image":{"@id":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/02\/dragndrop-feature-image.png","datePublished":"2022-02-24T15:17:55+00:00","dateModified":"2023-01-21T05:30:52+00:00","description":"In this tutorial, we\u2019re going to take a look at how you can build your very own drag-and-drop components using Stencil.","breadcrumb":{"@id":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#primaryimage","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/02\/dragndrop-feature-image.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/02\/dragndrop-feature-image.png","width":1600,"height":880},{"@type":"BreadcrumbList","@id":"https:\/\/ionic.io\/blog\/building-with-stencil-drag-and-drop-components#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ionic.io\/blog"},{"@type":"ListItem","position":2,"name":"Building with Stencil: Drag-and-Drop Components"}]},{"@type":"WebSite","@id":"https:\/\/ionic.io\/blog\/#website","url":"https:\/\/ionic.io\/blog\/","name":"ionic.io\/blog","description":"Build amazing native and progressive web apps with the web","publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ionic.io\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ionic.io\/blog\/#organization","name":"Ionic","url":"https:\/\/ionic.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","width":1920,"height":854,"caption":"Ionic"},"image":{"@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/ionicframework"]},{"@type":"Person","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/a3190e4d49187220d0c720f2ceab9b58","name":"Anthony Giuliano","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/10\/anthony-giuliano-profile-cropped-150x150.jpeg","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/10\/anthony-giuliano-profile-cropped-150x150.jpeg","caption":"Anthony Giuliano"},"sameAs":["https:\/\/www.linkedin.com\/in\/anthonygiuliano1\/","https:\/\/x.com\/a__giuliano"],"url":"https:\/\/ionic.io\/blog\/author\/anthonyionic-io"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2022\/02\/dragndrop-feature-image.png","_links":{"self":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/4069","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/users\/87"}],"replies":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/comments?post=4069"}],"version-history":[{"count":1,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/4069\/revisions"}],"predecessor-version":[{"id":4706,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/4069\/revisions\/4706"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media\/4070"}],"wp:attachment":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media?parent=4069"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/categories?post=4069"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/tags?post=4069"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}