fix: use $root for data attribute reads in Alpine interaction component

The extracted apCardInteraction component read data-mount-path,
data-csrf-token, and data-item-uid from this.$el inside interact(),
but $el may not be the x-data root when called from a child button
click. The old inline code used this.$root. Fixed by reading all
data attributes in init() and storing as component properties.
This commit is contained in:
Ricardo
2026-03-25 08:31:17 +01:00
parent 624a907946
commit 3265341189
2 changed files with 22 additions and 12 deletions

View File

@@ -23,19 +23,30 @@ document.addEventListener("alpine:init", () => {
likeCount: null, likeCount: null,
boostCount: null, boostCount: null,
// Stored from data attributes in init() — must use $root to guarantee
// we read from the x-data element, not a child element in event context.
_mountPath: "",
_csrfToken: "",
_itemUid: "",
_itemUrl: "",
init() { init() {
this.liked = this.$el.dataset.liked === "true"; const root = this.$root;
this.boosted = this.$el.dataset.boosted === "true"; this.liked = root.dataset.liked === "true";
const lc = this.$el.dataset.likeCount; this.boosted = root.dataset.boosted === "true";
const bc = this.$el.dataset.boostCount; this._mountPath = root.dataset.mountPath || "";
this._csrfToken = root.dataset.csrfToken || "";
this._itemUid = root.dataset.itemUid || "";
this._itemUrl = root.dataset.itemUrl || "";
const lc = root.dataset.likeCount;
const bc = root.dataset.boostCount;
this.likeCount = lc != null && lc !== "" ? Number(lc) : null; this.likeCount = lc != null && lc !== "" ? Number(lc) : null;
this.boostCount = bc != null && bc !== "" ? Number(bc) : null; this.boostCount = bc != null && bc !== "" ? Number(bc) : null;
}, },
async saveLater() { async saveLater() {
if (this.saved) return; if (this.saved) return;
const el = this.$el; const itemUrl = this._itemUrl;
const itemUrl = el.dataset.itemUrl;
try { try {
const res = await fetch("/readlater/save", { const res = await fetch("/readlater/save", {
method: "POST", method: "POST",
@@ -43,7 +54,7 @@ document.addEventListener("alpine:init", () => {
body: JSON.stringify({ body: JSON.stringify({
url: itemUrl, url: itemUrl,
title: title:
el.closest("article")?.querySelector("p")?.textContent?.substring(0, 80) || this.$root.closest("article")?.querySelector("p")?.textContent?.substring(0, 80) ||
itemUrl, itemUrl,
source: "activitypub", source: "activitypub",
}), }),
@@ -61,10 +72,9 @@ document.addEventListener("alpine:init", () => {
if (this.loading) return; if (this.loading) return;
this.loading = true; this.loading = true;
this.error = ""; this.error = "";
const el = this.$el; const itemUid = this._itemUid;
const itemUid = el.dataset.itemUid; const csrfToken = this._csrfToken;
const csrfToken = el.dataset.csrfToken; const basePath = this._mountPath;
const basePath = el.dataset.mountPath;
const prev = { const prev = {
liked: this.liked, liked: this.liked,
boosted: this.boosted, boosted: this.boosted,

View File

@@ -1,6 +1,6 @@
{ {
"name": "@rmdes/indiekit-endpoint-activitypub", "name": "@rmdes/indiekit-endpoint-activitypub",
"version": "3.9.1", "version": "3.9.2",
"description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.", "description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
"keywords": [ "keywords": [
"indiekit", "indiekit",