-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Any way to access $dispatch and other magic properties in "function components" ? #143
Comments
Why are you using object scope with external function call? You can use |
Kind of namespacing to prevent potential collisions. I simplified this example by keeping only the tabs part, but my data object can look more like I'm happy to know there is an easy fix, thank you @rzenkov. But I still wonder what to do in case of property collisions and/or code namespacing/organisation. I can imagine it being messy when you compose a lot of those "plugin functions". I leave @calebporzio and the other maintainers to decide if this is a discussion they want to have. Feel free to close the issue if not. |
@Lelectrolux As rzenkov pointed out, mixing global and component scoped functions is not easy. It's a massive simplification, but you can assume that you have access your scope variables and magic properties only when they show explicitly in the attribute string value of a x-* directive. The string is what is passed to the magic Alpine evaluator but the body of an external function will run on a different context so if you want to use a magic property there, you have to pass it in. For example, you can have <div x-data="{tabs: tabs('tab1') }" >
<button @click="tabs.select('tab1', $dispatch)">click me</button>
<!-- Note, dispatch is passed into the function from here -->
</div>
<script>
function tabs(initialTab) {
return {
current: initialTab,
select(tab, $dispatch) {
console.log(tab, $dispatch)
},
}
}
</script> and it would work. Long story short:
I hope it makes sense to you. |
@SimoTod Yeah, as soon as I read rzenkov answer I got what I did wrong. Painfully obvious once you see it, considering the way Alpinejs works under the hood. I actually already tried what you proposed and it worked, but having to pass manually the I still wonder if there is a smart api someone closer to the source could think about to deal with that. But like I said, feel free to close this. |
Hmm, minute ago i found that // in Component constructor
// Binded to this.$el
unobservedData.$dispatch = this.getDispatchFunction(el); One purpose for |
yeah, I suppose it would make sense to be able to call Like I think someone else mentioned, there would be a name collision with the magic If it's as simple as adding a default If there are weird gotchas or it's any more complex, we maybe should just punt on it. Thoughts? |
Yes,it is not as simple as it seemed at first. This behavior leads to I don't see simple way to avoid this behavior. (excepting reassigning IMHO Such mess up is not worth the end result, but docs apparently should reflect this. |
Moving discussion here from the issue @SimoTod mentioned above. |
Couple of options & thoughts here: When using the With regards to @calebporzio 's thoughts on adding a default |
It makes sense to me. |
Yeah. I'll throw in a PR to pass the |
Thanks for looking into this @ryangjchandler. Being new to Alpine I will say the $dispatch and $event not being available in the function component was not intuitive. I updated this CodePen with examples of all the magic variables being accessed inside a function: https://codepen.io/atomgiant/pen/ExVYdXz All of them appear to work fine except for $event and $dispatch. The $event one seems surprising so maybe I am missing something? My expectation was $event would reference the current event and $dispatch would dispatch based on the current $event.target which I believe lines up nicely with @ryangjchandler proposal. If the overriding of the $dispatch is too much of an issue I'm not sure this is possible but something like $el.dispatch or $event.dispatch (assuming I can access $event) would have been fine for my needs. |
@atomgiant The handler($event) {
...
} Should work fine currently. You have to make sure that you're doing |
We can maybe update the documentation to make clear what is available and when as well as adding the functionality Ryan is working on. |
Yeah for sure. I'm wondering now whether the documentation is growing a little too big in the README, @calebporzio any plans for a dedicated Alpine site yet? I'll be sure to update the README when I make my PR. |
Thanks @ryangjchandler. The @click=“handler” without parens was the missing link for me. I’d be happy to help with a PR for the doc Readme if you’re interested |
Yeah, feel free to make the PR. Im not sure whether it makes more sense to put it under the |
I'm not sure if my comment fits here. I "need" the $dispatch function in custom Modal.js file because this is what I want to achieve:
As you see is not a big deal but it would be nice something global like Alpine.$dispatch maybe? Anyway, awesome work caleb. |
If you are already in the real javascript part, you can trigger an event in the canonical way. $dispatch is just an utility helper for the html around a standard event dispatching. const event = new CustomEvent('modal:open:modal-1');
document.dispatchEvent(event) <button x-data @click="Modal.open('modal-1')">open</button>
<div id="modal-1" x-data="{...}" @modal:open:modal-1.document="...">
...
</div> |
Should we be closing this seeing as @atomgiant 's docs PR has gone in? There are a few workarounds to access
|
loving alpine, FWIW, I'm having a similar modal issue... in order to have one modal object at the Inside of the <a href="..." @click="$dispatch('modal-action', true)">...</a> And the outer shell is below. This may not be the right way to do this pattern entirely, but would also be nice to access the 2c :) <body
class="{{ body_class }}"
id="body"
x-data="{ 'isDialogOpen': false }"
@keydown.escape="isDialogOpen = false"
x-on:modal-action="isDialogOpen = $event.detail">
<div x-show="isDialogOpen" id="modal" class="modal">
<div
x-show="isDialogOpen"
x-transition:enter="transition ease-out duration-100 transform"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75 transform"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
class="modal-backdrop">
<div class=""></div>
</div>
<div
class="modal-dialog"
role="dialog"
aria-modal="true"
aria-labelledby="modal-headline">
<!-- modal contents -->
</div>
</div>
<!-- body contents -->
</body> Thanks again -- this + Tailwind = lifesaver! |
@timfee having the In this case you can make the modal be the component (have x-data on the div) and listen to |
Is there a way to replicate the // This works but can only be caught by a window scoped listener
window.dispatchEvent(new CustomEvent('my-event'))
// This does not bubble for some reason so I can only catch it with a listener on the root element
this.$el.dispatchEvent(new CustomEvent('my-event'))
// Again does not bubble
this.$refs.abc.dispatchEvent(new CustomEvent('my-event')) EDIT this.$el.dispatchEvent(new CustomEvent('my-event', {bubbles: true})); Is the same as (or at least as far as I can see) <button x-on:click="$dispatch('my-event')"><click/button> |
Hey everyone, I'm going to close this issue since it's quite old now and a handful of workarounds have been mentioned in the thread. For reference, the functionality of If anyone feels like this functionality needs to be re-evaluated, please re-open the issue or create a new one and reference this. |
Anyone wondering how to pass a param, you need to pass it as 'detail' in the object. |
Basically, I'm doing a tabs "plugin" and need to use
tab.scrollIntoView()
, but I can't use it as is, as alpine still has thetab
element hidden (x-show
'd out).I'm currently using a
setTimeout
but I feel it should/could be cleanerI tried to pass the
$dispatch
tox-data
(x-data="{tabs: tabs('tab1', $dispatch)}"
) but as I expected it doesn't work.I wonder if at least some of the magic properties could be stuck on the
Alpine
object for this use case ?The text was updated successfully, but these errors were encountered: