imacrayon / alpine-ajax

An Alpine.js plugin for building server-powered frontends.

Home Page:https://alpine-ajax.js.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Uncaught (in promise) Missing Target: #[object HTMLButtonElement] was not found in the current document.

hansaskov1 opened this issue · comments

I want to try out Alpine-ajax, but I can't get it to work. I have installed it by including it in the head of my HTML file. All seems to work until I interact with the page, and I get an error:

Uncaught (in promise) Missing Target: #[object HTMLButtonElement] was not found in the current document.
    E https://cdn.jsdelivr.net/npm/@imacrayon/alpine-ajax@0.5.0/dist/cdn.min.js:1
    j https://cdn.jsdelivr.net/npm/@imacrayon/alpine-ajax@0.5.0/dist/cdn.min.js:1
    j https://cdn.jsdelivr.net/npm/@imacrayon/alpine-ajax@0.5.0/dist/cdn.min.js:1
    r https://cdn.jsdelivr.net/npm/@imacrayon/alpine-ajax@0.5.0/dist/cdn.min.js:1
[cdn.min.js:1:8310](https://cdn.jsdelivr.net/npm/@imacrayon/alpine-ajax@0.5.0/dist/cdn.min.js)
    r https://cdn.jsdelivr.net/npm/@imacrayon/alpine-ajax@0.5.0/dist/cdn.min.js:1

Screenshot of the error:
Screenshot from 2024-03-19 19-23-12

I tried to reproduce the toggle example but this error has stumped me.

I am using Bun and Elysia for serving my code and i made a repository to reproduce this error:
https://github.com/hansaskov1/alpine-ajax-button

The entire source code is also here.

import { Elysia } from "elysia";
import { html } from "@elysiajs/html";

const Head = ({ children }: { children: undefined | {} }) => (
    <html lang="en">
        <head>
            <meta charset="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            <title>Document</title>

            {/* Alpine and Alpine Ajax */}
            <script defer src="https://cdn.jsdelivr.net/npm/@imacrayon/alpine-ajax@0.5.0/dist/cdn.min.js"></script>
            <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.11.1/dist/cdn.min.js"></script>

        </head>
        <body>
            {children}
        </body>
    </html>
);

const LikeButton = ({ id }: { id: string }) => (
    <form id="like" x-init x-target method="post" action={`/comments/${id}/like`}>
        <button name="id" value={id}>Like</button>
    </form>
)

const UnlikeButton = ({ id }: { id: string }) => (
    <form id="like" x-init x-target method="delete" action={`/comments/${id}/like`}>
        <button name="id" value={id} x-autofocus>Unlike</button>
    </form>
)

const app = new Elysia()
    .use(html())
    .get("/", () => (
        <Head>
            <LikeButton id={"1"} />
        </Head>
    ))
    .delete("/comments/:id/like", ({ params }) => (
        <LikeButton id={params.id} />
    ))
    .post("comments/:id/like", ({ params }) => (
        <UnlikeButton id={params.id} />
    ))

    .listen(3000);

console.log(
    `🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
);

Here is the rendered html from the browser

<html lang="en" class=" mrcjhi idc0_350">
   <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <script defer="" src="https://cdn.jsdelivr.net/npm/@imacrayon/alpine-ajax@0.5.0/dist/cdn.min.js"></script><script defer="" src="https://cdn.jsdelivr.net/npm/alpinejs@3.11.1/dist/cdn.min.js"></script>
   </head>
   <body>
      <form id="like" x-init="" x-target="button" method="post" action="/comments/1/like">
          <button name="id" value="1">Like</button>
      </form>
   </body>
</html>

Could someone please help me understand and resolve this issue?

Hi, so there's something a bit off with that rendered HTML:

<form id="like" x-init="" x-target="button" method="post" action="/comments/1/like">

x-target can be either empty (x-target) or x-target="like" but,x-target="button" is the cause of the error. The template code you shared appears fine, I'm not sure where the value of button would be coming from.

I think i copy pasted the html from my browser incorrectly. The x-target is empty and not button. Sorry for the confusion.

Here is the actual html

<html lang="en" class=" dnvyzo idc0_350">
    <head><meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script defer="" src="https://cdn.jsdelivr.net/npm/@imacrayon/alpine-ajax@0.5.0/dist/cdn.min.js"></script>
        <script defer="" src="https://cdn.jsdelivr.net/npm/alpinejs@3.11.1/dist/cdn.min.js"></script>
    </head>
    <body>
        <form id="like" x-init="" x-target="" method="post" action="/comments/1/like">
            <button name="id" value="1">Like</button>
        </form>
    </body>
</html>

Based on your answer i am assuming x-target="" should be x-target instead for it to target itself. But i'm not sure if a can configre my html render to not parse it like this

Here is a picture from the browser:
Screenshot from 2024-03-19 20-40-16

Ah, I was able to track down the problem.

It's some browser DOM weirdness and some unsafe programming on my part. Since your submit button is named id. In JavaScript, document.querySelector('form').id will actually reference the <button> element inside the form instead of the id attribute on the form 😩. I should be using document.querySelector('form').getAttribute('id') instead to prevent that name conflict.

I'll try to get a patch out really soon, but in the meantime if you change that button name to something like name="comment_id" you should have things working.

Amazing! You're so fast. Thank you very much.

Quite a hilarious bug. Good thing you found it.
This also explains why removing name="id" and value="1" from my buttons fixed the issue

Thank you for the thorough details!