Browse Source

Introduce x-teleport values/modifiers (#3268)

* introduce values for x-teleport to append or prepend a node

* provide a test for new x-teleport values

* Change prepend/append to modifiers

Co-authored-by: Josh Hanley <josh@hitsystems.com.au>
Jeremias Wolff 2 years ago
parent
commit
90af0fa3ff

+ 11 - 2
packages/alpinejs/src/directives/x-teleport.js

@@ -4,7 +4,7 @@ import { mutateDom } from "../mutation"
 import { addScopeToNode } from "../scope"
 import { addScopeToNode } from "../scope"
 import { warn } from "../utils/warn"
 import { warn } from "../utils/warn"
 
 
-directive('teleport', (el, { expression }, { cleanup }) => {
+directive('teleport', (el, { modifiers, expression }, { cleanup }) => {
     if (el.tagName.toLowerCase() !== 'template') warn('x-teleport can only be used on a <template> tag', el)
     if (el.tagName.toLowerCase() !== 'template') warn('x-teleport can only be used on a <template> tag', el)
 
 
     let target = document.querySelector(expression)
     let target = document.querySelector(expression)
@@ -31,7 +31,16 @@ directive('teleport', (el, { expression }, { cleanup }) => {
     addScopeToNode(clone, {}, el)
     addScopeToNode(clone, {}, el)
 
 
     mutateDom(() => {
     mutateDom(() => {
-        target.appendChild(clone)
+        if (modifiers.includes('prepend')) {
+            // insert element before the target
+            target.parentNode.insertBefore(clone, target)
+        } else if (modifiers.includes('append')) {
+            // insert element after the target
+            target.parentNode.insertBefore(clone, target.nextSibling)
+        } else {
+            // origin
+            target.appendChild(clone)
+        }
 
 
         initTree(clone)
         initTree(clone)
 
 

+ 38 - 0
tests/cypress/integration/directives/x-teleport.spec.js

@@ -19,6 +19,44 @@ test('can use a x-teleport',
     },
     },
 )
 )
 
 
+test('can use a x-teleport.append',
+    [html`
+        <div x-data="{ count: 1 }" id="a">
+            <button @click="count++">Inc</button>
+
+            <template x-teleport.append="#b">
+                <span x-text="count"></span>
+            </template>
+        </div>
+
+        <div id="b"></div>
+    `],
+    ({ get }) => {
+        get('#b + span').should(haveText('1'))
+        get('button').click()
+        get('#b + span').should(haveText('2'))
+    },
+)
+
+test('can use a x-teleport.prepend',
+    [html`
+        <div x-data="{ count: 1 }" id="a">
+            <button @click="count++">Inc</button>
+
+            <template x-teleport.prepend="#b">
+                <span x-text="count"></span>
+            </template>
+        </div>
+
+        <div id="b"></div>
+    `],
+    ({ get }) => {
+        get('#a + span').should(haveText('1'))
+        get('button').click()
+        get('#a + span').should(haveText('2'))
+    },
+)
+
 test('can teleport multiple',
 test('can teleport multiple',
     [html`
     [html`
         <div x-data="{ count: 1 }" id="a">
         <div x-data="{ count: 1 }" id="a">