Cascader

Cascade selection box.

When To Use#

  • When you need to select from a set of associated data set. Such as province/city/district, company level, things classification.

  • When selecting from a large data set, with multi-stage classification separated for easy selection.

  • Chooses cascade items in one float layer for better user experience.

Examples

Please select

Cascade selection box for selecting province/city/district.

expand codeexpand code
import { Cascader } from 'antd';

const options = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    children: [
      {
        value: 'hangzhou',
        label: 'Hangzhou',
        children: [
          {
            value: 'xihu',
            label: 'West Lake',
          },
        ],
      },
    ],
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    children: [
      {
        value: 'nanjing',
        label: 'Nanjing',
        children: [
          {
            value: 'zhonghuamen',
            label: 'Zhong Hua Men',
          },
        ],
      },
    ],
  },
];

function onChange(value) {
  console.log(value);
}

export default () => <Cascader options={options} onChange={onChange} placeholder="Please select" />;
Unselect Change city

Separate trigger button and result.

expand codeexpand code
import { Cascader } from 'antd';

const options = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    children: [
      {
        value: 'hangzhou',
        label: 'Hangzhou',
      },
    ],
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    children: [
      {
        value: 'nanjing',
        label: 'Nanjing',
      },
    ],
  },
];

class CitySwitcher extends React.Component {
  state = {
    text: 'Unselect',
  };

  onChange = (value, selectedOptions) => {
    this.setState({
      text: selectedOptions.map(o => o.label).join(', '),
    });
  };

  render() {
    return (
      <span>
        {this.state.text}
        &nbsp;
        <Cascader options={options} onChange={this.onChange}>
          <a href="#">Change city</a>
        </Cascader>
      </span>
    );
  }
}

export default () => <CitySwitcher />;

Disable option by specifying the disabled property in options.

expand codeexpand code
import { Cascader } from 'antd';

const options = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    children: [
      {
        value: 'hangzhou',
        label: 'Hangzhou',
        children: [
          {
            value: 'xihu',
            label: 'West Lake',
          },
        ],
      },
    ],
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    disabled: true,
    children: [
      {
        value: 'nanjing',
        label: 'Nanjing',
        children: [
          {
            value: 'zhonghuamen',
            label: 'Zhong Hua Men',
          },
        ],
      },
    ],
  },
];

function onChange(value) {
  console.log(value);
}

export default () => <Cascader options={options} onChange={onChange} />;

Select multiple options

expand codeexpand code
import { Cascader } from 'antd';

const options = [
  {
    label: 'Light',
    value: 'light',
    children: new Array(20)
      .fill(null)
      .map((_, index) => ({ label: `Number ${index}`, value: index })),
  },
  {
    label: 'Bamboo',
    value: 'bamboo',
    children: [
      {
        label: 'Little',
        value: 'little',
        children: [
          {
            label: 'Toy Fish',
            value: 'fish',
          },
          {
            label: 'Toy Cards',
            value: 'cards',
          },
          {
            label: 'Toy Bird',
            value: 'bird',
          },
        ],
      },
    ],
  },
];

const App = () => {
  const onChange = value => {
    console.log(value);
  };
  return (
    <Cascader
      style={{ width: '100%' }}
      options={options}
      onChange={onChange}
      multiple
      maxTagCount="responsive"
    />
  );
};

export default App;
4.17.0






Cascade selection box of different sizes.

expand codeexpand code
import { Cascader } from 'antd';

const options = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    children: [
      {
        value: 'hangzhou',
        label: 'Hangzhou',
        children: [
          {
            value: 'xihu',
            label: 'West Lake',
          },
        ],
      },
    ],
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    children: [
      {
        value: 'nanjing',
        label: 'Nanjing',
        children: [
          {
            value: 'zhonghuamen',
            label: 'Zhong Hua Men',
          },
        ],
      },
    ],
  },
];

function onChange(value) {
  console.log(value);
}

export default () => (
  <>
    <Cascader size="large" options={options} onChange={onChange} />
    <br />
    <br />
    <Cascader options={options} onChange={onChange} />
    <br />
    <br />
    <Cascader size="small" options={options} onChange={onChange} />
    <br />
    <br />
  </>
);
Please select

Custom field names.

expand codeexpand code
import { Cascader } from 'antd';

const options = [
  {
    code: 'zhejiang',
    name: 'Zhejiang',
    items: [
      {
        code: 'hangzhou',
        name: 'Hangzhou',
        items: [
          {
            code: 'xihu',
            name: 'West Lake',
          },
        ],
      },
    ],
  },
  {
    code: 'jiangsu',
    name: 'Jiangsu',
    items: [
      {
        code: 'nanjing',
        name: 'Nanjing',
        items: [
          {
            code: 'zhonghuamen',
            name: 'Zhong Hua Men',
          },
        ],
      },
    ],
  },
];

function onChange(value) {
  console.log(value);
}

export default () => (
  <Cascader
    fieldNames={{ label: 'name', value: 'code', children: 'items' }}
    options={options}
    onChange={onChange}
    placeholder="Please select"
  />
);


Please select

You can manually specify the position of the popup via placement.

expand codeexpand code
import { Cascader, Radio } from 'antd';

const options = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    children: [
      {
        value: 'hangzhou',
        label: 'Hangzhou',
        children: [
          {
            value: 'xihu',
            label: 'West Lake',
          },
        ],
      },
    ],
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    children: [
      {
        value: 'nanjing',
        label: 'Nanjing',
        children: [
          {
            value: 'zhonghuamen',
            label: 'Zhong Hua Men',
          },
        ],
      },
    ],
  },
];

const SetPlacementDemo = () => {
  const [placement, SetPlacement] = React.useState('topLeft');

  const placementChange = e => {
    SetPlacement(e.target.value);
  };

  return (
    <>
      <Radio.Group value={placement} onChange={placementChange}>
        <Radio.Button value="topLeft">topLeft</Radio.Button>
        <Radio.Button value="topRight">topRight</Radio.Button>
        <Radio.Button value="bottomLeft">bottomLeft</Radio.Button>
        <Radio.Button value="bottomRight">bottomRight</Radio.Button>
      </Radio.Group>
      <br />
      <br />
      <Cascader options={options} placeholder="Please select" placement={placement} />
    </>
  );
};

export default () => <SetPlacementDemo />;
Zhejiang / Hangzhou / West Lake

Specifies default value by an array.

expand codeexpand code
import { Cascader } from 'antd';

const options = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    children: [
      {
        value: 'hangzhou',
        label: 'Hangzhou',
        children: [
          {
            value: 'xihu',
            label: 'West Lake',
          },
        ],
      },
    ],
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    children: [
      {
        value: 'nanjing',
        label: 'Nanjing',
        children: [
          {
            value: 'zhonghuamen',
            label: 'Zhong Hua Men',
          },
        ],
      },
    ],
  },
];

function onChange(value) {
  console.log(value);
}

export default () => (
  <Cascader defaultValue={['zhejiang', 'hangzhou', 'xihu']} options={options} onChange={onChange} />
);

Hover to expand sub menu, click to select option.

expand codeexpand code
import { Cascader } from 'antd';

const options = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    children: [
      {
        value: 'hangzhou',
        label: 'Hangzhou',
        children: [
          {
            value: 'xihu',
            label: 'West Lake',
          },
        ],
      },
    ],
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    children: [
      {
        value: 'nanjing',
        label: 'Nanjing',
        children: [
          {
            value: 'zhonghuamen',
            label: 'Zhong Hua Men',
          },
        ],
      },
    ],
  },
];

function onChange(value) {
  console.log(value);
}

// Just show the latest item.
function displayRender(label) {
  return label[label.length - 1];
}

export default () => (
  <Cascader
    options={options}
    expandTrigger="hover"
    displayRender={displayRender}
    onChange={onChange}
  />
);

Allow only select parent options.

expand codeexpand code
import { Cascader } from 'antd';

const options = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    children: [
      {
        value: 'hangzhou',
        label: 'Hanzhou',
        children: [
          {
            value: 'xihu',
            label: 'West Lake',
          },
        ],
      },
    ],
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    children: [
      {
        value: 'nanjing',
        label: 'Nanjing',
        children: [
          {
            value: 'zhonghuamen',
            label: 'Zhong Hua Men',
          },
        ],
      },
    ],
  },
];

function onChange(value) {
  console.log(value);
}

export default () => <Cascader options={options} onChange={onChange} changeOnSelect />;


The way show selected item in box using ShowCheckedStrategy.

expand codeexpand code
import { Cascader } from 'antd';

const { SHOW_CHILD } = Cascader;

const options = [
  {
    label: 'Light',
    value: 'light',
    children: new Array(20)
      .fill(null)
      .map((_, index) => ({ label: `Number ${index}`, value: index })),
  },
  {
    label: 'Bamboo',
    value: 'bamboo',
    children: [
      {
        label: 'Little',
        value: 'little',
        children: [
          {
            label: 'Toy Fish',
            value: 'fish',
          },
          {
            label: 'Toy Cards',
            value: 'cards',
          },
          {
            label: 'Toy Bird',
            value: 'bird',
          },
        ],
      },
    ],
  },
];

const App = () => {
  const onChange = value => {
    console.log(value);
  };
  return (
    <>
      <Cascader
        style={{ width: '100%' }}
        options={options}
        onChange={onChange}
        multiple
        maxTagCount="responsive"
        showCheckedStrategy={SHOW_CHILD}
        defaultValue={[
          ['bamboo', 'little', 'fish'],
          ['bamboo', 'little', 'cards'],
          ['bamboo', 'little', 'bird'],
        ]}
      />
      <br />
      <br />
      <Cascader
        style={{ width: '100%' }}
        options={options}
        onChange={onChange}
        multiple
        maxTagCount="responsive"
        defaultValue={['bamboo']}
      />
    </>
  );
};

ReactDOM.render(<App />, mountNode);
4.20.0
Zhejiang / Hangzhou / West Lake (752100)

For instance, add an external link after the selected value.

expand codeexpand code
import { Cascader } from 'antd';

const options = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    children: [
      {
        value: 'hangzhou',
        label: 'Hangzhou',
        children: [
          {
            value: 'xihu',
            label: 'West Lake',
            code: 752100,
          },
        ],
      },
    ],
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    children: [
      {
        value: 'nanjing',
        label: 'Nanjing',
        children: [
          {
            value: 'zhonghuamen',
            label: 'Zhong Hua Men',
            code: 453400,
          },
        ],
      },
    ],
  },
];

function handleAreaClick(e, label, option) {
  e.stopPropagation();
  console.log('clicked', label, option);
}

const displayRender = (labels, selectedOptions) =>
  labels.map((label, i) => {
    const option = selectedOptions[i];
    if (i === labels.length - 1) {
      return (
        <span key={option.value}>
          {label} (<a onClick={e => handleAreaClick(e, label, option)}>{option.code}</a>)
        </span>
      );
    }
    return <span key={option.value}>{label} / </span>;
  });

export default () => (
  <Cascader
    options={options}
    defaultValue={['zhejiang', 'hangzhou', 'xihu']}
    displayRender={displayRender}
    style={{ width: '100%' }}
  />
);

Load options lazily with loadData.

Note: loadData cannot work with showSearch.

expand codeexpand code
import { Cascader } from 'antd';

const optionLists = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    isLeaf: false,
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    isLeaf: false,
  },
];

const LazyOptions = () => {
  const [options, setOptions] = React.useState(optionLists);

  const onChange = (value, selectedOptions) => {
    console.log(value, selectedOptions);
  };

  const loadData = selectedOptions => {
    const targetOption = selectedOptions[selectedOptions.length - 1];
    targetOption.loading = true;

    // load options lazily
    setTimeout(() => {
      targetOption.loading = false;
      targetOption.children = [
        {
          label: `${targetOption.label} Dynamic 1`,
          value: 'dynamic1',
        },
        {
          label: `${targetOption.label} Dynamic 2`,
          value: 'dynamic2',
        },
      ];
      setOptions([...options]);
    }, 1000);
  };

  return <Cascader options={options} loadData={loadData} onChange={onChange} changeOnSelect />;
};

export default () => <LazyOptions />;
Please select

Customize the dropdown menu via dropdownRender.

expand codeexpand code
import { Cascader, Divider } from 'antd';

const options = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    children: [
      {
        value: 'hangzhou',
        label: 'Hangzhou',
        children: [
          {
            value: 'xihu',
            label: 'West Lake',
          },
        ],
      },
    ],
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    children: [
      {
        value: 'nanjing',
        label: 'Nanjing',
        children: [
          {
            value: 'zhonghuamen',
            label: 'Zhong Hua Men',
          },
        ],
      },
    ],
  },
];

function dropdownRender(menus) {
  return (
    <div>
      {menus}
      <Divider style={{ margin: 0 }} />
      <div style={{ padding: 8 }}>The footer is not very short.</div>
    </div>
  );
}

export default () => (
  <Cascader options={options} dropdownRender={dropdownRender} placeholder="Please select" />
);
Error
Warning multiple

Add status to Cascader with status, which could be error or warning.

expand codeexpand code
import { Cascader, Space } from 'antd';

const Validation: React.FC = () => (
  <Space direction="vertical">
    <Cascader status="error" placeholder="Error" />
    <Cascader status="warning" multiple placeholder="Warning multiple" />
  </Space>
);

export default () => <Validation />;
4.19.0

API#

<Cascader options={options} onChange={onChange} />
PropertyDescriptionTypeDefaultVersion
allowClearWhether allow clearbooleantrue
autoFocusIf get focus when component mountedbooleanfalse
borderedWhether has border stylebooleantrue
clearIconThe custom clear iconReactNode-
changeOnSelect(Work on single select) Change value on each selection if set to true, see above demo for detailsbooleanfalse
classNameThe additional css classstring-
defaultValueInitial selected valuestring[] | number[][]
disabledWhether disabled selectbooleanfalse
displayRenderThe render function of displaying selected options(label, selectedOptions) => ReactNodelabel => label.join(/)multiple: 4.18.0
dropdownClassNameThe additional className of popup overlaystring-4.17.0
dropdownRenderCustomize dropdown content(menus: ReactNode) => ReactNode-4.4.0
expandIconCustomize the current item expand iconReactNode-4.4.0
expandTriggerexpand current item when click or hover, one of click hoverstringclick
fieldNamesCustom field name for label and value and childrenobject{ label: label, value: value, children: children }
getPopupContainerParent Node which the selector should be rendered to. Default to body. When position issues happen, try to modify it into scrollable content and position it relative. examplefunction(triggerNode)() => document.body
loadDataTo load option lazily, and it cannot work with showSearch(selectedOptions) => void-
maxTagCountMax tag count to show. responsive will cost render performancenumber | responsive-4.17.0
maxTagPlaceholderPlaceholder for not showing tagsReactNode | function(omittedValues)-4.17.0
notFoundContentSpecify content to show when no result matchesstringNot Found
openSet visible of cascader popupboolean-4.17.0
optionsThe data options of cascadeOption[]-
placeholderThe input placeholderstringPlease select
placementUse preset popup align config from builtinPlacementsbottomLeft bottomRight topLeft topRightbottomLeft4.17.0
showSearchWhether show search input in single modeboolean | Objectfalse
sizeThe input sizelarge | middle | small-
statusSet validation status'error' | 'warning'-4.19.0
styleThe additional styleCSSProperties-
suffixIconThe custom suffix iconReactNode-
tagRenderCustomize tag render when multiple(props) => ReactNode-4.17.0
valueThe selected valuestring[] | number[]-
onChangeCallback when finishing cascader select(value, selectedOptions) => void-
onDropdownVisibleChangeCallback when popup shown or hidden(value) => void-4.17.0
multipleSupport multiple or notboolean-4.17.0
showCheckedStrategyThe way show selected item in box. SHOW_CHILD: just show child treeNode. Cascader.SHOW_PARENT: just show parent treeNode (when all child treeNode under the parent treeNode are checked)Cascader.SHOW_PARENT | Cascader.SHOW_CHILDCascader.SHOW_PARENT4.20.0
removeIconThe custom remove iconReactNode-
searchValueSet search value,Need work with showSearchstring-4.17.0
onSearchThe callback function triggered when input changed(search: string) => void-4.17.0
dropdownMenuColumnStyleThe style of the drop-down menu columnCSSProperties-
loadingIconThe apparence of lazy loading (now is useless)ReactNode-

showSearch#

PropertyDescriptionTypeDefaultVersion
filterThe function will receive two arguments, inputValue and option, if the function returns true, the option will be included in the filtered set; Otherwise, it will be excludedfunction(inputValue, path): boolean-
limitSet the count of filtered itemsnumber | false50
matchInputWidthWhether the width of list matches input, (how it looks)booleantrue
renderUsed to render filtered optionsfunction(inputValue, path): ReactNode-
sortUsed to sort filtered optionsfunction(a, b, inputValue)-

Option#

interface Option {
  value: string | number;
  label?: React.ReactNode;
  disabled?: boolean;
  children?: Option[];
  // Determines if this is a leaf node(effective when `loadData` is specified).
  // `false` will force trade TreeNode as a parent node.
  // Show expand icon even if the current node has no children.
  isLeaf?: boolean;
}

Methods#

NameDescriptionVersion
blur()Remove focus
focus()Get focus