blueprint icon indicating copy to clipboard operation
blueprint copied to clipboard

Rendering `Collapse` within `HTMLTable` doesn't seem to work, what am I doing wrong?

Open rreed opened this issue 5 years ago • 5 comments

Environment

  • Package version(s): 3.17.1
  • Browser and OS versions: Electron 3.0.7

Question

I don't really get the behavior that I expect from the interaction between Collapse and HTMLTable. Basically, I have a list of table rows that need to expand into larger groups, e.g.:

foo v
    sub foo 1
    sub foo 2
    sub foo 3
bar ^
baz ^

Clicking foo should expand or collapse the subcategories as necessary. Pretty straightforward.

The problem is that neither of the things I expect to work actually work when the Collapse contents are generated from props. I tried two things:

render() {
        return (
            <React.Fragment>
                <tr>
                    ...
                </tr>

                {redacted.map((...) =>
                    <Collapse isOpen={this.state.isOpen} component="tr" keepChildrenMounted={true}>
                        ...
                    </Collapse>
                )}
            </React.Fragment>
        )
    }

which renders a ton of collapses as trs, as well as having Collapse outside of the map call, which creates one single Collapse with a bunch of programmatically generated trs.

Both of these fail for the same reason, because the contents of Collapse are still a div:

<tr class="bp3-collapse">
    <div class="bp3-collapse-body" aria-hidden="true" style="transform: translateY(0px);">   
        <td>blah</td>
         ... a bunch more td tags
    </div>
</tr>

which just throws:

Warning: validateDOMNesting(...): <div> cannot appear as a child of <tr>.
    in div
    in tr
    in Blueprint3.Collapse (created by Redacted)

So, uh, what am I doing wrong? The documentation says that component is used for rendering collapses inside tables, so I know this is POSSIBLE. :p Thanks in advance.

rreed avatar Jul 09 '19 20:07 rreed

as of core/src/components/collapse/collapse.tsx line 161~175

return React.createElement(
            this.props.component,
            {
                className: classNames(Classes.COLLAPSE, this.props.className),
                style: containerStyle,
            },
            <div
                className={Classes.COLLAPSE_BODY}
                ref={this.contentsRefHandler}
                style={contentsStyle}
                aria-hidden={!isContentVisible && this.props.keepChildrenMounted}
            >
                {shouldRenderChildren ? this.props.children : null}
            </div>,
        );

<Collapse/> does render itself in <tr/> but wraps children you passed in a <div/>.

li-yifei avatar Jul 10 '19 02:07 li-yifei

So how does this possibly work with tables, if you can't do a tr with td children and no div?

rreed avatar Jul 10 '19 03:07 rreed

I'm having this issue as well. The best I can come up with is wrapping the Collapse element in a

with a colSpan that cover the entire row, then embedding a table inside the Collapse. That's dumb, though, and it screws up the tabular formatting.

rbeard0330 avatar Jan 22 '20 05:01 rbeard0330

If anyone is still encountering this issue, can you please use the issue template and provide a code sandbox we can poke at to debug? Thanks

adidahiya avatar Jan 22 '20 17:01 adidahiya

@adidahiya I think at this point this should just be considered a documentation bug.

The docs say "Useful when rendering a Collapse inside a <table>, for instance.", but really it should say "Useful when rendering a Collapse inside a <td>, for instance."

Because there's no way the current implementation could render valid HTML if setting component="tr" or component="table", since a div will always be rendered wrapping the children.

justinbhopper avatar Mar 17 '22 19:03 justinbhopper