-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
Events in spread props #5112
Comments
In cases like this I fire a single known event name such as I'm pretty sure what you're suggesting isn't possible, since the expectation would be that events could be computed at runtime and appended to components, but I'm not 100% sure of that. |
Thanks for your answer @antony, and sorry for the late answer here ! Using a generic event is another way to do it, indeed. I didn't think about this solution. So it's definitely not a blocking issue, but sure, if there is way to standardize the way dynamic components are used (compared to a static one), it would be a plus. The |
This would be really useful to allow reusing behavior between multiple components, similar to React Hooks. For example, I'd like to try to port React Aria to Svelte. These hooks return DOM props that should be spread onto an element to provide some behavior. Part of the functionality that is returned are event handlers. I'd like to avoid needing to manually copy the events over one by one so the hook implementation details are hidden. <button {...$buttonProps} on:pointerdown={$buttonProps.onPointerDown} on:pointerup={$buttonProps.onPointerUp}>
Clicked {count} {count === 1 ? 'time' : 'times'}
</button> Is there a good way to do this given the compiler won't know at build time what events are needed? Should I make a wrapper that does |
I think you could probably use an action and pass in the buttonProps there,then manually add event listeners for each of the handlers. |
@devongovett I believe |
Ooh nice. Thanks for the super quick responses. Heading to sleep now but will try in the morning! 😊 |
@devongovett Here is a use action example: |
Update: it worked! 🎉 https://github.com/devongovett/svelte-hooks |
I was so excited to see that there was a decent workaround for this missing feature (using an action like
Does anyone know why actions (i.e., Svelte's closest equivalent to react hooks, which is the background where I'm coming from) can't be applied to components? Okay, I mean, I understand that it would have to work a little bit differently because we don't necessarily have a single root element (though #5218 could provide a way to mark which element(s) are considered the root), but I wish the And, does anyone have a good generic reusable solution for how to attach a bunch of event handlers (defined in an object in your component) to a child component used inside of your component? Needless to say, I would like to see this feature implemented, so that we could just spread ("pass through") an object containing Since that current behavior is surprising/useless, could that be an argument in favor of making Of course I know nothing about how hard this would be to implement; I'm speaking only in the context of developer experience as a Svelte user... But the fact that it's pretty easy to implement in a generic/reusable way for elements means I am at least hopeful that it could be easy to make something like this available for components too... 🤞 |
I also looked into how to create renderless components such as React Aria and Headless UI in Svelte. |
Relevent Issue: #5218 @TylerRick I put together something that works on a component at runtime, but it requires the component to provide access to its' owned elements. The component exposes references to the elements through @LeanderG This doesn't use actions, but probably won't work with SSR. This does break component encapsulation. However, there could be a case where someone created a component as part of an npm package, but they may have forgotten to support some Typically, you would submit a PR, let it merge, and then either set your |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
No stale. |
I also find this annoying & a source of clunkiness in the framework. The ergonomics of |
Is anyone currently working on the issue? It's a shame that a feature that is meant to improve DX actually breaks some powerful design patterns. Couple of cross-framework libraries depend on similar features in Vue and React to append features to components in a composable fashion. |
UPDATE 8/13/22: Since originally posting this comment, I've come to think there must be some sort of flag set on the element/component tag itself granting such "special" props the ability to be dynamically assigned. Otherwise, you leave your app open to an XSS-like attack. I'd like to revive this Feature Suggestion, as I don't think the I opened another related issue—that I'll close—that duplicates this one. Here were the contents: Describe the problemOn several occasions, I've found myself taking in the props for components in an array of objects and then building out the component instances by iterating over the array using an Each object in the array will have unique directives such as event handlers ( It would be great if there were a way to naturally spread directive-props onto components as well. Describe the proposed solutionI propose adding a new convention when spreading props where Svelte will accept event handlers by their natural HTML name and convert them to their For example: <script>
import MyComponent from './MyComponent.svelte';
let data = [
{
id: 184638,
postCount: 17,
$$on_click: () => console.log('Hello world'),
$$transition_fade: true,
},
{
id: 473892,
postCount: 4,
$$on_click: doSomething,
$$transition_fade: {
y: 200,
duration: 2000,
},
},
];
</script>
{#each data as child}
<MyComponent
{...child}
/>
{/each} This would automatically spread the {
id: 184638,
postCount: 17,
'on:click': () => console.log('Hello world'),
} Regarding the naming, I also considered wrapping the Svelte convention in quotes as you did to keep it exactly the same. If this passes, I keep going back and forth on what would make more sense between these two—
Alternatives consideredCurrently, to work around this, I am spreading the other non-event-handler props into a separate variable using a <script>
import MyComponent from './MyComponent.svelte';
let data = [
{
id: 184638,
postCount: 17,
$$on_click: () => console.log('Hello world'),
},
{
id: 473892,
postCount: 4,
$$on_click: doSomething,
},
];
</script>
{#each data as child}
{@const { $$on_click, ...props } = child}
<MyComponent
{...props}
on:click={$$on_click}
/>
{/each} While I do value the explicit nature of this method, it does often require creating an intermediary wrapper component as the component(s) I'm feeding into often forward the |
This seems to also stop UI frameworks such as Chakra and Flowbite to port their stuff to Svelte. Is there any info to this wrt what needs to be done to move this feature forward? |
Id suggest for the above example there is little point in using spread props for events. The idea behind spreading the events is so you can pass the event handler into the component dynamically. If you need to specify the event name, then passing in a dynamic function can already be achieved without additional syntax, simply by handling the implementation inside the function which handles the click handler. Im not a fan of dumping logic into templates.
|
This is super important, every UI that is slightly customizable by the user needs that, so it's a pretty basic requirement for any simple UI and would be also a no-brainer in other frameworks. Yeah, there are work-arounds but they are clunky/cumbersome. So, no need to block Svelte users here. |
Closing as spreading events is supported in Svelte 5 |
Is your feature request related to a problem? Please describe.
At the moment, there is no way to manage component events for a dynamic component, with spread props. Let consider this example:
on:action
will not be called.REPL here
Describe the solution you'd like
To have the code above working 😊
Describe alternatives you've considered
The workaround is to consider callbacks instead of events, like this :
But then the code in Comp must be different compared to a normal dispatch usage.
How important is this feature to you?
It's just annoying because the workaround works pretty well, but maybe it can be a useful feature to keep consistency with the spread props.
The text was updated successfully, but these errors were encountered: