Skip to content

Commit

Permalink
Fix x-ignore being added after using Alpine.morph (#47)
Browse files Browse the repository at this point in the history
* Add failing test

* Do not rerun x-load when morphing elements
  • Loading branch information
SimoTod authored Dec 11, 2024
1 parent 316af0e commit 85a7016
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 49 deletions.
36 changes: 20 additions & 16 deletions dist/async-alpine.cjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,24 +241,28 @@ function async_alpine_default(Alpine) {
alias = path;
};
const syncHandler = (el) => {
if (el._x_async) return;
el._x_async = "init";
el._x_ignore = true;
el.setAttribute(ignoreAttr, "");
Alpine.skipDuringClone(() => {
if (el._x_async) return;
el._x_async = "init";
el._x_ignore = true;
el.setAttribute(ignoreAttr, "");
})();
};
const handler = async (el) => {
if (el._x_async !== "init") return;
el._x_async = "await";
const { name, strategy } = elementPrep(el);
await awaitRequirements({
name,
strategy,
el,
id: el.id || index()
});
await download(name);
activate(el);
el._x_async = "loaded";
Alpine.skipDuringClone(async () => {
if (el._x_async !== "init") return;
el._x_async = "await";
const { name, strategy } = elementPrep(el);
await awaitRequirements({
name,
strategy,
el,
id: el.id || index()
});
await download(name);
activate(el);
el._x_async = "loaded";
})();
};
handler.inline = syncHandler;
Alpine.directive(directive, handler).before("ignore");
Expand Down
36 changes: 20 additions & 16 deletions dist/async-alpine.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,24 +206,28 @@ function async_alpine_default(Alpine) {
alias = path;
};
const syncHandler = (el) => {
if (el._x_async) return;
el._x_async = "init";
el._x_ignore = true;
el.setAttribute(ignoreAttr, "");
Alpine.skipDuringClone(() => {
if (el._x_async) return;
el._x_async = "init";
el._x_ignore = true;
el.setAttribute(ignoreAttr, "");
})();
};
const handler = async (el) => {
if (el._x_async !== "init") return;
el._x_async = "await";
const { name, strategy } = elementPrep(el);
await awaitRequirements({
name,
strategy,
el,
id: el.id || index()
});
await download(name);
activate(el);
el._x_async = "loaded";
Alpine.skipDuringClone(async () => {
if (el._x_async !== "init") return;
el._x_async = "await";
const { name, strategy } = elementPrep(el);
await awaitRequirements({
name,
strategy,
el,
id: el.id || index()
});
await download(name);
activate(el);
el._x_async = "loaded";
})();
};
handler.inline = syncHandler;
Alpine.directive(directive, handler).before("ignore");
Expand Down
2 changes: 1 addition & 1 deletion dist/async-alpine.script.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 20 additions & 16 deletions src/async-alpine.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,26 +77,30 @@ export default function (Alpine) {
*/
// inline handler adds x-ignore immediately and synchronously
const syncHandler = (el) => {
if (el._x_async) return
el._x_async = 'init'
el._x_ignore = true
el.setAttribute(ignoreAttr, '')
Alpine.skipDuringClone(() => {
if (el._x_async) return
el._x_async = 'init'
el._x_ignore = true
el.setAttribute(ignoreAttr, '')
})()
}

// the bulk of processing happens within Alpine's deferred handler
const handler = async (el) => {
if (el._x_async !== 'init') return
el._x_async = 'await'
const { name, strategy } = elementPrep(el)
await awaitRequirements({
name,
strategy,
el,
id: el.id || index(),
})
await download(name)
activate(el)
el._x_async = 'loaded'
Alpine.skipDuringClone(async () => {
if (el._x_async !== 'init') return
el._x_async = 'await'
const { name, strategy } = elementPrep(el)
await awaitRequirements({
name,
strategy,
el,
id: el.id || index(),
})
await download(name)
activate(el)
el._x_async = 'loaded'
})()
}

// register handler functions and directive
Expand Down
37 changes: 37 additions & 0 deletions tests/alpine/morph/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<title>morph - Async Alpine tests</title>
</head>
<body>
<p>Tests Alpine 'morph'. Passes if x-ignore is not re-added after morphing (pressing 'Run Morph' button).</p>

<div
data-testid="test"
x-load
x-load-src="/tests/assets/complex.js"
x-data="complex"
x-text="'testing123'"
>
</div>

<button data-testid="button">Run morph</button>

<script type="module">
import Alpine from 'https://cdn.skypack.dev/alpinejs'
import AsyncAlpine from '/dist/async-alpine.esm.js'
import AlpineMorph from 'https://cdn.skypack.dev/@alpinejs/morph'
Alpine.plugin(AsyncAlpine)
Alpine.plugin(AlpineMorph)
Alpine.start()
window.Alpine = Alpine // Alpine morph plugin needs Alpine as a global

document.querySelector('button').addEventListener('click', () => {
Alpine.morph(document.querySelector('div'), document.querySelector('div').outerHTML)
})
</script>
</body>
</html>
12 changes: 12 additions & 0 deletions tests/alpine/morph/morph.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { test, expect } from '@playwright/test'

test('alpine/morph', async ({ page }) => {
await page.goto('/tests/alpine/morph/')
await expect(page.getByTestId('test'))
.toHaveText('testing123')
await page.getByTestId('button').click()
await expect(page.getByTestId('test'))
.not.toHaveAttribute('x-ignore')
await expect(page.getByTestId('test'))
.toHaveText('testing123')
});
1 change: 1 addition & 0 deletions tests/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ <h2>Alpine Features</h2>
<li><a href="/tests/alpine/teleport/">x-teleport</a></li>
<li><a href="/tests/alpine/if/">x-if</a></li>
<li><a href="/tests/alpine/id/">x-id</a></li>
<li><a href="/tests/alpine/morph/">morph</a></li>
</ul>

<h2>Loading Method</h2>
Expand Down

0 comments on commit 85a7016

Please sign in to comment.