Browse Source

Merge pull request #449 from SimoTod/bug/mutation-observer-resets-nested-component

MutationObserver reset x-data when nested components are moved around
Caleb Porzio 5 years ago
parent
commit
63d1b91561
4 changed files with 48 additions and 3 deletions
  1. 1 1
      dist/alpine-ie11.js
  2. 1 1
      dist/alpine.js
  3. 1 1
      src/component.js
  4. 45 0
      test/mutations.spec.js

+ 1 - 1
dist/alpine-ie11.js

@@ -6991,7 +6991,7 @@
 
                 if (node.nodeType !== 1 || node.__x_inserted_me) return;
 
-                if (node.matches('[x-data]')) {
+                if (node.matches('[x-data]') && !node.__x) {
                   node.__x = new Component(node);
                   return;
                 }

+ 1 - 1
dist/alpine.js

@@ -1583,7 +1583,7 @@
             mutations[i].addedNodes.forEach(node => {
               if (node.nodeType !== 1 || node.__x_inserted_me) return;
 
-              if (node.matches('[x-data]')) {
+              if (node.matches('[x-data]') && !node.__x) {
                 node.__x = new Component(node);
                 return;
               }

+ 1 - 1
src/component.js

@@ -353,7 +353,7 @@ export default class Component {
                     mutations[i].addedNodes.forEach(node => {
                         if (node.nodeType !== 1 || node.__x_inserted_me) return
 
-                        if (node.matches('[x-data]')) {
+                        if (node.matches('[x-data]') && ! node.__x) {
                             node.__x = new Component(node)
                             return
                         }

+ 45 - 0
test/mutations.spec.js

@@ -1,4 +1,5 @@
 import Alpine from 'alpinejs'
+import { wait } from '@testing-library/dom'
 
 test('catch disconnected nodes that were used as targets for any mutations', async () => {
     const runObservers = []
@@ -23,3 +24,47 @@ test('catch disconnected nodes that were used as targets for any mutations', asy
         }
     ]))
 })
+
+test('mutationObserver doesn\'t reset data when reparenting nested components', async () => {
+
+    const runObservers = []
+
+    global.MutationObserver = class {
+        constructor(callback) {
+            runObservers.push(callback)
+        }
+        observe() {}
+    }
+
+    document.body.innerHTML = `
+        <div x-data>
+            <div id="a">
+                <button x-data="{counter: 1}" x-text="counter" @click="counter = 2"></button>
+            </div>
+            <div id="b">
+            </div>
+        </div>
+    `
+
+    Alpine.start()
+
+    expect(document.querySelector('button').innerText).toEqual(1)
+
+    document.querySelector('button').click()
+
+    await wait(() => { expect(document.querySelector('button').innerText).toEqual(2) })
+
+    // Move the component and run the observer
+    document.getElementById('b').appendChild(document.querySelector('button'))
+    runObservers.forEach(cb => {
+        cb([
+            {
+                target:  document.getElementById('b'),
+                type: 'childList',
+                addedNodes: [ document.querySelector('button') ],
+            }
+        ])
+    })
+
+    await wait(() => { expect(document.querySelector('button').innerText).toEqual(2) })
+})