You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
And since now we finally have a way to represent an event with both, the name and the target, using the JS struct, we should probably deprecate support for %{name: name, target: target} and use the JS struct instead. I'll work on a PR for that.
I forgot to mention that currently, we only accept the target as option so value, loading or any other will not be handled if you try to pass them as above. For those cases, you need to use JS.push explicitly for now.
I was starting to play around with this and I noticed that it might not be a good idea to handle events that way.
The problem is that Phoenix's JS API does not allow setting any option like target or loading after we call JS.push. The first argument of JS.push must always be a string. If you try to pass a %JS{}, it will break with a no function clause matching in Phoenix.LiveView.JS.push/2.
I still think is valuable to add syntactic sugar for JS.push like:
as it's the most common use for it, but the first argument (in this case, @some_event) will have to be a string, not a %JS{}.
So for cases like you described, where you need to set the options later, the best solution would be to change the type of the prop from :event from :string or maybe a :tuple like {event_as_string, opts} which you could handle later in your component, updating the opts you need before calling JS.push.
I would not recommend using it as :event and then handling %{name: ..., target: ...} yourself because, as I mentioned, we plan to deprecate it and eventually remove it.
If the JS API evolves and allow us to set options on an existing JS struct, then we could reconsider adding this feature.
I'm closing this for now. Feel free to reopen it in case you have any updates.
I'm not sure I follow with respect to setting the options later. Doesn't my dodgy workaround set them when adding the push operation to the %JS{}?
JS.push takes a %JS{}, but it also requires an event string. Can't we collect the target from the event and pass it as an option to JS.push? If the first arg passed to :on-click is a string, we pass that straight to JS.push. And we accept the same opts in :on-click as JS.push?
But that doesn't really help for :on-click{JS.push(@event_prop, value: ...) |> JS.hide(...) |> JS.dispatch(...)}, which is why I thought we would need to provide our own JS module which delegates to LiveView's, except for push, so we can extract the event name and target from the event prop. Whether or not that is possible is a question I do not know the answer to 😄
@simonmcconnell I totally misunderstood the whole thing. Thanks for persisting on the issue. I believe we should work on replacing %{name: ..., target: ...} with a JS struct as soon as possible as it would not only fix the issue but it would also make the API more flexible allowing users to update events as they wish without introducing a new custom API.
Activity
msaraiva commentedon Mar 7, 2022
Hi @simonmcconnell!
Ideally, we should have
:on-*accepting something like:which would already handle the default target and be equivalent to:
And since now we finally have a way to represent an event with both, the name and the target, using the JS struct, we should probably deprecate support for
%{name: name, target: target}and use the JS struct instead. I'll work on a PR for that.msaraiva commentedon Mar 7, 2022
I forgot to mention that currently, we only accept the
targetas option sovalue,loadingor any other will not be handled if you try to pass them as above. For those cases, you need to useJS.pushexplicitly for now.simonmcconnell commentedon Mar 7, 2022
Hi marlus. When you say "as above", are you referring to your ideal future scenario?
<button :on-click={@some_event, value: ..., loading: ...}>button</button>?msaraiva commentedon Mar 13, 2022
@simonmcconnell yes!
msaraiva commentedon Mar 13, 2022
Hey @simonmcconnell!
I was starting to play around with this and I noticed that it might not be a good idea to handle events that way.The problem is that Phoenix's JS API does not allow setting any option liketargetorloadingafter we callJS.push. The first argument ofJS.pushmust always be a string. If you try to pass a%JS{}, it will break with ano function clause matching in Phoenix.LiveView.JS.push/2.I still think is valuable to add syntactic sugar for
JS.pushlike:as it's the most common use for it, but the first argument (in this case,
@some_event) will have to be a string, not a%JS{}.So for cases like you described, where you need to set the options later, the best solution would be to change the type of the prop from:eventfrom:stringor maybe a:tuplelike{event_as_string, opts}which you could handle later in your component, updating the opts you need before callingJS.push.I would not recommend using it as
:eventand then handling%{name: ..., target: ...}yourself because, as I mentioned, we plan to deprecate it and eventually remove it.If the JS API evolves and allow us to set options on an existing JS struct, then we could reconsider adding this feature.I'm closing this for now. Feel free to reopen it in case you have any updates.simonmcconnell commentedon Mar 14, 2022
Thanks for taking a look.
I'm not sure I follow with respect to setting the options later. Doesn't my dodgy workaround set them when adding the
pushoperation to the%JS{}?JS.pushtakes a%JS{}, but it also requires aneventstring. Can't we collect thetargetfrom theeventand pass it as an option toJS.push? If the first arg passed to:on-clickis a string, we pass that straight toJS.push. And we accept the sameoptsin:on-clickasJS.push?But that doesn't really help for
:on-click{JS.push(@event_prop, value: ...) |> JS.hide(...) |> JS.dispatch(...)}, which is why I thought we would need to provide our ownJSmodule which delegates to LiveView's, except forpush, so we can extract the event name and target from the event prop. Whether or not that is possible is a question I do not know the answer to 😄LiveView source:
msaraiva commentedon Mar 14, 2022
@simonmcconnell I totally misunderstood the whole thing. Thanks for persisting on the issue. I believe we should work on replacing
%{name: ..., target: ...}with a JS struct as soon as possible as it would not only fix the issue but it would also make the API more flexible allowing users to update events as they wish without introducing a new custom API.I'm reopening it. Thanks again!
simonmcconnell commentedon Mar 14, 2022
No problem. Let me know if you want a hand with it.