Search code examples
admin-on-rest

Conditional Tab/FormTab rendering in TabbedShowLayout/TabbedForm


I would like to display a Tab inside the TabbedShowLayout only if the record has a specific property. I tried to create a custom component as below:

const EventsTab = ({...props, record}) => {
  return record && record.hasEvents &&
  <Tab label="Tab2">
    test
  </Tab>
}

and then add it inside the Show layout as:

<Show {...props}>
  <TabbedShowLayout>
    <Tab label="Tab1">
      <MetricsComp {...props} />
    </Tab>
    <EventsTab {...props}/>
  </TabbedShowLayout>
</Show>

but I get the following error: uncaught at finalize Invariant Violation: EventsTab(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.

Admin-on-rest allows conditional rendering of a component (like in How to access record's internals in Show/Edit/Create) but not a Tab. Is there any workaround?


Solution

  • We had to do something similar - Unfortunately we don't have access of record in Show but we have in TabbedShowLayout. So we decided to create a custom TabbbedShowLayout with render() of TabbedShowLayout changed like that:

    render() {
        const {
            children,
            contentContainerStyle,
            record,
            resource,
            basePath,
            translate,
            version,
        } = this.props;
        let changedChildren = children;
    
        if (record.excludeTab) {
            changedChildren = [];
    
            for (let i=0; i<children.length; i++) {
                if (children[i] instanceof Array) {
                    changedChildren.push(children[i]);
                } else if (children[i] instanceof Object 
                           && children[i].props.label !== "TabToExcludeLabel") {
                    changedChildren.push(children[i]);
                }
            }
    
        }
        return (
            <div style={divStyle} key={version}>
                <Tabs
                    value={this.state.value}
                    onChange={this.handleChange}
                    contentContainerStyle={contentContainerStyle}
                >
                    {React.Children.map(
                        changedChildren,
                        (tab, index) => ....
        )
     }