Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trigger JS components from outside Alpine #24

Open
cbenz opened this issue Nov 20, 2020 · 3 comments
Open

Trigger JS components from outside Alpine #24

cbenz opened this issue Nov 20, 2020 · 3 comments

Comments

@cbenz
Copy link

cbenz commented Nov 20, 2020

Hi, I would like to trigger a JS component like dropdown or dialog from "outside" the component, in particular from an event handler of an element which is not handled by the component itself. This would mean not using the trigger button allowing normally to open the dialog as shown in the examples.

The specific use case is that I'm using an external library (http://tabulator.info/) that generates some "action buttons" in a cell of the table, and I would like to trigger the opening of the dialog when clicking on that action button.

What I would like to do (pseudo-code imitating a React-like UI lib):

<button on:click={(event) => {
  dialogElement.sendToAlpine("open") // or something like that!
}>

<div ref={dialogElement} x-data="dialog()">
  // There is no trigger button here
  <div class="dialog" x-spread="dialog" x-cloak>
    <div class="dialog-content">
      ...
    </div>
  </div>
</div>

Is it possible as-is, or by adapting the Alpine components of dialog/dropdown/etc? Or should I rewrite the JS components using Svelte/Vue/React?

I dived into the JavaScript code (e.g. dialog.js) and tried to hack around with Svelte, here is what I did on Svelte REPL.

This works but is in my sense a bit "overkill" and has remaining questions/problems:

  • that's strange to have to put the trigger button inside the dialog
  • how to close the dialog from a Svelte event handler?
  • the dialogAction function feels quite hacky
  • overall it does not solve the use case explained above: I still have to render the trigger button as a child of <div x-spread="trigger">, otherwise the Alpine component won't see it

Afterthought: would it be possible to break the Alpine JS components into base functions that could still be called by the Alpine JS components, but could be also be called by Svelte/Vue/React components?

Anyway, thanks for the excellent work and for your reactivity about following Tailwind v2 release!

@praveenjuge
Copy link
Owner

I know what you are saying, it's annoying for me too to build the dialog component in the same place as the trigger.
But I don't think there is a way to separate those for now. I'll ask some alpine people about how to make it better.

Also checkout headlessui which will I'm thinking of using once it's released.

I'll keep this issue open until we find a solution.

@HugoDF
Copy link

HugoDF commented Nov 22, 2020

There's a couple of ways to interact with Alpine components from outside of them.

The cleanest is to send custom events (dispatchEvent(new CustomEvent('my-event'))) and listen to that event on the Alpine side.

You can also find the root DOM node and read/write the Alpine.js state at .__x.$data

@drifteaur
Copy link

For reference, here's a good article on how to trigger custom events from outside: https://tonylea.com/setting-alpine-data-outside-of-the-component

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants