Some thoughts on sharing behaviour between components using prepend
#376
Replies: 2 comments 4 replies
-
One thing that came up recently in my use of components which would be made possible by the addition of a root element is for |
Beta Was this translation helpful? Give feedback.
-
@thomasbrus this is looking very similar to something I'm working on at the moment which I posted about previously #341 - I'd see one benefit of the approach I've got as being able to easily constrain what values are allowed for each property - any thoughts/comments are very welcome! |
Beta Was this translation helpful? Give feedback.
-
Hi!
We are in the process of setting up a design system using
view_component
. I ran into the need to share behaviour between components for consistency & code reuse.Behaviour shared between all components
It'd be cool if all components accept a
:html
property that can be used to apply arbitrary html attributes on the root element of the component (think adding an domid
for controller tests ordata-target
to hook a component up to a Stimulus controller.Specific behaviour shared between some components
Some components share the same properties with the same values, such as
size: :small | :normal | :large
, or:color
to pass a color scheme to use, or:icon
if the component accepts an icon name, and so on.Goal is to mix & match, i.e. some component have a
:size
and:color
while another provides:size
and:icon
as properties.Implementation
To solve this, I used the following pattern shown below. Thought it might be helpful to share :)
(it depends on Ruby 2.7+ and this PR to remove the need for explicit #initialize method).First add the properties shared between all components to
ApplicationComponent
and callsuper(**opts)
from child components:Then extract specific properties into their own modules in
app/components/concerns
. By usingprepend
, they can callsuper
in their initialize method and pass the "rest" props (**opts
) up to the parent class. This preserves the behaviour of amissing keyword
error when a non-existing property is passed to the component.This is also the place to provide default arguments and perform validation (via
raise
for example).Then finally the implementation of the actual components is pretty straight forward:
And then to use the components with the various properties that are now available:
Feedback
Would love to hear from others what you think of this pattern. Or what other patterns you found useful to share behaviour between components!
Beta Was this translation helpful? Give feedback.
All reactions