Search code examples
react-admin

react-admin - ChipField conditional color in List view


I'm trying to conditionally display a ChipField component in a react-admin List view. It's similar to How do you conditionally show fields in "Show" component in react-admin? but for list, and I haven't found a working way when using a list.

import React from 'react';
import { ChipField, Datagrid, ImageField, List, ListController, TextField } from 'react-admin';
import { ListProps } from '../../types/admin/ListProps';
import ProductBulkActionButtons from './ProductBulkActionButtons';

const ProductList = (props: ListProps): JSX.Element => {
  console.debug('ProductList.props', props);
  return (
    <ListController {...props}>
      {(controllerProps) => {
        console.debug('ProductList.controllerProps', controllerProps);
        return (
          <List
            {...props}
            {...controllerProps}
            sort={{
              field: 'titleEN',
              order: 'DESC',
            }}
            bulkActionButtons={<ProductBulkActionButtons />}
          >
            <Datagrid rowClick="edit">
              <ImageField source={'images[0].url'} title={'images[0]title'} label={'Image'} />
              <TextField source="titleEN" label={'Title (EN)'} />
              <TextField source="titleFR" label={'Title (FR)'} />
              {/*<ArrayField source="images"><SingleFieldList><ChipField source="id" /></SingleFieldList></ArrayField>*/}
              {/*<ReferenceArrayField source="imagesIds" reference="images"><TextField source="id" /></ReferenceArrayField>*/}
              <TextField source="customer.label" label={'Customer'} />
              <TextField source="price" />
              <ChipField source="status" color={'primary'} />
            </Datagrid>
          </List>
        );
      }}
    </ListController>
  );
};

export default ProductList;

This renders the following: enter image description here

What I'd like to do, is to use another color when the status is DRAFT. Currently, it uses the primary color for all records.

<ChipField source="status" color={'primary'} />

I tried using a similar method to https://stackoverflow.com/a/51068735/2391795, but I could only access the whole data and not control per-row rendering.

Interactive demo at https://nrn-admin-display-product-status.now.sh/#/Product


Solution

  • According to Conditional Formatting, you have to create a component to replace the field component and pass the props to it. Then you can control the source and the record props.

    You can change the color of the ChipField by creating a class with backgroundColor to the color you want and apply it to the className prop.

    An example that changes the color to the <ChipField> the DRAFT status:

    import { makeStyles } from '@material-ui/core/styles';
    import classnames from 'classnames';
    
    const useStyles = makeStyles({
      draft: { backgroundColor: '#74fd74' },
    });
    
    const ColoredChipField = props => {
      const classes = useStyles();
    
      const isDraft = v => v.toUpperCase() === 'DRAFT';
    
      return (
        <ChipField
          className={classnames({
            [classes.draft]: isDraft(props.record[props.source]),
          })}
          {...props} 
        />
      );
    };
    

    and then use it like this:

    (
      <List {...props}>
        <Datagrid rowClick="edit">
          <TextField source="titleEN" label="Title (EN)"/>
          <TextField source="titleFR" label="Title (FR)"/>
          <ColoredChipField source="status" color="primary"/>
        </Datagrid>
      </List>
    );
    

    Please check this working Stackblitz:

    Stackblitz List App