Format of Material UI nested List components is wack

I am building a custom component that will have nested Material UI List components.

When I try and render the component the UI is wacked.

The generated html looks fine:

<div>
    <h5>Asset Sources</h5>
    <ul class="jss1 jss2">
        <li class="jss5 jss8 jss13">
            <div class="jss17">
                <span class="jss23 jss30 jss20">ASSETS: $12.18</span>
            </div>
            <ul class="jss1 jss2">
                <li class="jss5 jss8 jss13">
                    <div class="jss17">
                        <span class="jss23 jss30 jss20">Current Assets: $15.18</span>
                    </div>
                    <ul class="jss1 jss2">
                        <li class="jss5 jss8 jss13">
                            <div class="jss17">
                                <span class="jss23 jss30 jss20">Bank Accounts: $13.18</span>
                            </div>
                            <ul class="jss1 jss2">
                                <li class="jss5 jss8 jss13">
                                    <div class="jss17">
                                        <span class="jss23 jss30 jss20">My Checking: $5.08</span>
                                    </div>
                                </li>
                                <li class="jss5 jss8 jss13">
                                    <div class="jss17">
                                        <span class="jss23 jss30 jss20">My Other Checking: $173713.94</span>
                                    </div>
                                </li>
                                <li class="jss5 jss8 jss13">
                                    <div class="jss17">
                                        <span class="jss23 jss30 jss20">PayPal Account: $12.09</span>
                                    </div>
                                </li>
                            </ul>
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</div> 

Here is sample data:

{
  assetSources: [
    {
      name: "ASSETS",
      value: 12.18,
      company: null,
      remote_id: null,
      sub_items: [
        {
          name: "Current Assets",
          value: 15.18,
          company: null,
          remote_id: null,
          sub_items: [
            {
              name: "Bank Accounts",
              value: 13.18,
              company: null,
              remote_id: null,
              sub_items: [
                {
                  name: "My Checking",
                  value: 5.08,
                  company: null,
                  remote_id: "136",
                  sub_items: [],
                },
                {
                  name: "My Other Checking",
                  value: 173713.94,
                  company: null,
                  remote_id: "137",
                  sub_items: [],
                },
                {
                  name: "PayPal Account",
                  value: 12.09,
                  company: null,
                  remote_id: "184",
                  sub_items: [],
                },
              ],
            },
          ],
        },
      ],
    },
  ]
}

Here is the iFrame source I am using:

<style>
  body {
    margin: 0;
  }
</style>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/@material-ui/core@3.9.3/umd/material-ui.production.min.js"></script>

<div id="balanceSheetDisplay"></div>

<script type="text/babel">
  const { ListSubheader, List, ListItem, ListItemText, Box } = window["material-ui"]
  
  const CustomNestedList = ({ triggerQuery, model, modelUpdate }) => (
    <div>
      <h5>Asset Sources</h5>
      <NestedList model={model.assetSources} />
    </div>
  )
  
  const NestedList = ({ model }) => (
    <List>
      {model.map((item) => (
        <ListItemComponent key={item.name} item={item} />
      ))}
    </List>
  )

  const ListItemComponent = ({ item }) => (
    <ListItem>
      <ListItemText
        primary={`${item.name}: $${item.value}`}/>
        {item.sub_items && item.sub_items.length > 0 && (
          <NestedList model={item.sub_items} />
        )}
    </ListItem>
  )

  const ConnectedComponent = Retool.connectReactComponent(CustomNestedList);
  const container = document.getElementById('balanceSheetDisplay')
  const root = ReactDOM.createRoot(container)
  root.render(<ConnectedComponent />)
</script>```

Hey @Ron_West!

Thanks for attending OH today :slightly_smiling_face:

I took a look at the examples you mentioned here. It looks like it might be helpful to pull the package from a later version, you might try

https://unpkg.com/@mui/material@latest/umd/material-ui.production.min.js

Using that, a custom component based on their example (without icons) might look something like the following:

Code
<style>
  body {
    margin: 0;
  }
</style>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/@mui/material@latest/umd/material-ui.production.min.js"></script>

<div id="balanceSheetDisplay"></div>

<script type="text/babel">
const {
  ListSubheader,
  List,
  ListItem,
  ListItemText,
  ListItemButton,
  Collapse,
} = MaterialUI;

const CustomNestedList = ({ triggerQuery, model, modelUpdate }) => (
  <div>
    <List
      sx={{ width: "100%", maxWidth: 360, bgcolor: "background.paper" }}
      component="nav"
      aria-labelledby="nested-list-subheader"
      subheader={
        <ListSubheader component="div" id="nested-list-subheader">
          Asset Sources
        </ListSubheader>
      }
    >
      <NestedList model={model.assetSources} open={true} />
    </List>
  </div>
);

const NestedList = ({ model, open, nesting }) => (
  <Collapse in={open} timeout="auto" unmountOnExit>
    <List>
      {model.map((item) => (
        <ListItemComponent key={item.name} item={item} nesting={nesting} />
      ))}
    </List>
  </Collapse>
);

const ListItemComponent = ({ item, nesting = 2 }) => {
  const [open, setOpen] = React.useState(false);

  const handleClick = () => {
    setOpen(!open);
  };
  return (
    <li>
      <ListItemButton onClick={handleClick} sx={{ pl: nesting }}>
        <ListItemText primary={`${item.name}: $${item.value}`} />
      </ListItemButton>
      {item.sub_items && item.sub_items.length > 0 && (
        <NestedList model={item.sub_items} open={open} nesting={nesting + 2}/>
      )}
    </li>
  );
};

const ConnectedComponent = Retool.connectReactComponent(CustomNestedList);
const container = document.getElementById("balanceSheetDisplay");
const root = ReactDOM.createRoot(container);
root.render(<ConnectedComponent />);

</script>

Did some additional messing around to get it working with the code you have, you might want to alter it a bit as well but you can check it out in the attached JSON file!

material_ui_nested_list.json (9.6 KB)

Thank you so much @Kabirdas!

OH was fun :slight_smile:

I will give this a try.

@Kabirdas

I am not able to get the sx property on any tags to work. It looks like there might be some sort of parsing issue which is causing the settings defined on that property from being applied. If you open up your console do you see things like this:

error in computeTemplateStringDependencies width: "100%", maxWidth: 360, bgcolor: "background.paper" SyntaxError: Unexpected token :

That error looks like it's coming from Retool trying to compute its dependency graph based on the custom component having {{}} in it. That would mean the error is innocuous since {{}} aren't actually parsed within custom component scripts but you should be able to get rid of it by adding some white space (e.g. sx={ { width: "100%", maxWidth: 360, bgcolor: "background.paper" } }).

What is it that you're trying to do with the sx property?

Thanks @Kabirdas

I am trying to control the layout of the component. I will give that a try.