Closed TomS- closed 4 years ago
@TomS- In this case you can pass $dispatch
and $el
into x-init
(x-init="init($dispatch, $el)"
) and even add it to this
. Magic properties are available on the instance for other methods, just not the x-init
handler.
<div x-data="page()">
<div @custom="handleCustom($event)">
<div x-data="nested()" x-init="init($dispatch, $el)">
This is a nested component that dispatches an event of type "custom" on x-init
</div>
</div>
<label>Output in parent component: "<span x-text="output"></span>"</label>
</div>
<script>
function nested() {
return {
init($dispatch, $el) {
$el.innerText = "Edited by x-init handler: " + $el.innerText;
$dispatch("custom", {
some: "data",
more: "data"
});
}
};
}
function page() {
return {
output: "",
handleCustom(event) {
this.output = `Received Custom event "${
event.type
}" with payload ${JSON.stringify(event.detail)}`;
}
};
}
</script>
See a full codepen at: https://codepen.io/hugodf/pen/WNvEMLL
I agree that $dispatch()
should be callable like this.$dispatch()
in a function.
Currently, $dispatch()
uses the element the expression is registered on the dispatch the event from.
I imagine a good default for this.$dispatch()
would be to use the root element of the Alpine component to do the dispatching?
Thoughts?
@calebporzio the magic properties (like $dispatch) are callable from functions, I think it's just for x-init that they're not on "this"
Hi @HugoDF I think $dispatch
is available when used inside a directive since it's added by saferEval and saferEvalReturn but if you use it in a function as Tom said, it does not work.
For example
<div x-data="controller()" x-on:custom-event="foo = $event.detail.newValue">
<span x-text="foo"></span>
<button x-on:click="test()">Turn 'bar' to 'baz'</button>
</div>
<script type="text/javascript">
function controller() {
return {
foo: 'bar',
test: function() {
this.$dispatch('custom-event', {newValue: 'baz'})
}
}
}
</script>
However, it's possible to pass $dispatch in any directives as you said, which feels correct since it preserves the source element.
<div x-data="controller()" x-on:custom-event="foo = $event.detail.newValue">
<span x-text="foo"></span>
<button x-on:click="test($dispatch)">Turn 'bar' to 'baz'</button>
</div>
<script type="text/javascript">
function controller() {
return {
foo: 'bar',
test: function($dispatch) {
$dispatch('custom-event', {newValue: 'baz'})
}
}
}
</script>
@calebporzio and others. I'm a bit torn about this.$dispatch.
If we add it, we should make clear in the documentation that the event will be triggered on the root element of that component because there will be edge cases where it won't be so obvious.
For instance, this snippet would not update foo since the event is triggered on <div x-data="controller()">
despite the function being called from the button.
<div x-data="controller()">
<div x-on:custom-event="foo = $event.detail.newValue">
<span x-text="foo"></span>
<button x-on:click="test()">Turn 'bar' to 'baz'</button>
</div>
</div>
<script type="text/javascript">
function controller() {
return {
foo: 'bar',
test: function() {
this.$dispatch('custom-event', {newValue: 'baz'})
}
}
}
</script>
The way I see it, it's something that will be difficult to remove later and adds edge cases.
The solution IMO is to document & educate how to pass $dispatch around instead of adding to "this".
@HugoDF I'm absolutely fine with passing it through to the function, even other magic properties such as $event. It makes sense to educate people as it seems these properties are not available making functions less functional. I think this is a documentation thing more than a change to core.
Closing this in favour of https://github.com/alpinejs/alpine/issues/143 (which covers the same topics I believe).
Feel free to reopen or start a discussion
I have some logic that runs and is complicated as it checks a url against a regex and various other things. After that I want to dispatch an event so I can capture it on the parent component. Unfortuntely when using the $dispatch magic property using
this.$dispatch
within the function I get the errorthis.$dispatch is not a function
I checked
this
and I was getting the proxy as expected. It would be good if we could use the magic properties within the functions too.EDIT: Example