metal.js icon indicating copy to clipboard operation
metal.js copied to clipboard

Utilities to modify this.config.children

Open AngeloYoun opened this issue 8 years ago • 9 comments

There are cases where you would want to maintain decoupling between 2 components while still passing configs from one to another such as

render(
    <Filter data={this.data}>
        <List />
    </Filter>
);

In this case the Filter component should filter a given set of data and pass it onto whatever child component is nested within it.

In React, this can be achieved with a combination of React.Children helper util and React.cloneElement.

render() {
    const children = React.Children.map(  
        this.props.children,
        (child) => {
            React.cloneElement(
                child,
                {
                    data: this.filteredData
                }
            )
        }
    );

    return (
        <div>
            {children}
        </div>
    );
 }

AngeloYoun avatar May 11 '16 18:05 AngeloYoun

Interesting use case. I had already thought about adding some utilities to deal with children, but didn't know this specific usage. Thanks for the idea.

mairatma avatar May 11 '16 18:05 mairatma

Hey Maira,

This use case is one that would be very helpful for the Loop team as well. The basic idea is that children would be handled as an array of metal-jsx components.

In addition to the use case Angelo explained, this would allow us to conditionally render individual children: https://github.com/liferay/liferay-plugins-ee/blob/ee-6.2.x/portlets/loop-portlet/docroot/js/src/components/Tabs.js#L50

Or to be able to access props that are passed to a child component: https://github.com/liferay/liferay-plugins-ee/blob/ee-6.2.x/portlets/loop-portlet/docroot/js/src/components/creator/LoopEditor.js#L439

All of this could be achieved simply by passing an array of children to an attribute on the component instead of rendering them as children in the html, but then we would lose one of the advantages of JSX which is getting to write javascript that looks very similar to html.

I hope this helps to explain a few more use cases. Let me know if you need any clarifications.

Thanks!

ethib137 avatar May 19 '16 18:05 ethib137

Thanks for this, these use cases really helped me understand better what's needed here.

I started working on some things to allow these utilities to exist, but I was always thinking more of utility functions, while what you showed me clearly has more power than that, since you can simply access the children array directly and use only the parts you wish in a very intuitive manner.

Having only utility functions would work, but I really like this flexibility with the children array, and I think I already know what I can do to allow all that :)

I'll try to get this working (or at least some part of it) this week.

mairatma avatar May 19 '16 19:05 mairatma

Done, it's already possible to do both use cases that @ethib137 showed me here: rendering individual children and accessing children data.

All that's left is adding some utility functions like the ones @AngeloYoun mentioned, to help clone elements for example. This can already be done manually though, so try it out and let me know what you guys think :)

I still need to properly document how to use children, and have an issue for this already, but for now just know that the api is similar to the one from react, the main difference being that the props property is of course called config in Metal.js.

mairatma avatar May 20 '16 21:05 mairatma

Thanks Maira! This is super helpful!

ethib137 avatar May 20 '16 23:05 ethib137

Thanks Maira :D

AngeloYoun avatar May 23 '16 22:05 AngeloYoun

This issue was moved to metal/metal#11

mairatma avatar Jul 05 '16 17:07 mairatma

This issue was moved back.

mairatma avatar Jul 21 '16 20:07 mairatma

Hey @AngeloYoun, we are still missing the utility functions in order to close this one, right?

brunobasto avatar Jan 08 '17 17:01 brunobasto