CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-rc-cascader

A comprehensive cascading select component for React applications that enables hierarchical option selection through a dropdown interface

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

multiple-selection.mddocs/

Multiple Selection

Multiple selection capabilities with checkbox support, different display strategies, and hierarchical selection management. Enables users to select multiple items across different levels of the cascading hierarchy.

Capabilities

Multiple Selection Configuration

Enable and configure multiple selection behavior.

interface MultipleSelectionProps<
  OptionType extends DefaultOptionType,
  ValueField extends keyof OptionType
> {
  /** Enable multiple selection mode */
  checkable: true | React.ReactNode;
  
  /** Strategy for displaying selected items */
  showCheckedStrategy?: ShowCheckedStrategy;
  
  /** Clear search value when selecting an item */
  autoClearSearchValue?: boolean;
  
  /** Multiple selection value type */
  value?: (string | number)[][];
  
  /** Multiple selection change handler */
  onChange?: (
    value: (string | number)[][],
    selectOptions: OptionType[][]
  ) => void;
}

Show Checked Strategy

Control how selected items are displayed in multiple selection mode.

type ShowCheckedStrategy = 'SHOW_PARENT' | 'SHOW_CHILD';

// Available as constants on Cascader component
Cascader.SHOW_PARENT: 'SHOW_PARENT';
Cascader.SHOW_CHILD: 'SHOW_CHILD';

// Access via destructuring
const { SHOW_PARENT, SHOW_CHILD } = Cascader;

Multiple Selection Value Types

Type definitions for multiple selection values and callbacks.

/** Multiple selection value format - array of value paths */
type MultipleValueType = (string | number)[][];

/** Multiple selection options format - array of option paths */
type MultipleOptionsType<OptionType> = OptionType[][];

/** Multiple selection change callback */
interface MultipleChangeCallback<OptionType> {
  (value: MultipleValueType, selectOptions: MultipleOptionsType<OptionType>): void;
}

Option Checkbox Configuration

Configure checkbox behavior for individual options.

interface CheckboxOptionType extends BaseOptionType {
  /** Disable checkbox for this specific option */
  disableCheckbox?: boolean;
  
  /** Disable the entire option (selection and checkbox) */
  disabled?: boolean;
}

Usage Examples

Basic Multiple Selection

import React, { useState } from 'react';
import Cascader from 'rc-cascader';

const options = [
  {
    label: 'Technology',
    value: 'tech',
    children: [
      {
        label: 'Frontend',
        value: 'frontend',
        children: [
          { label: 'React', value: 'react' },
          { label: 'Vue', value: 'vue' },
          { label: 'Angular', value: 'angular' }
        ]
      },
      {
        label: 'Backend',
        value: 'backend',
        children: [
          { label: 'Node.js', value: 'nodejs' },
          { label: 'Python', value: 'python' }
        ]
      }
    ]
  }
];

const BasicMultipleExample = () => {
  const [value, setValue] = useState([]);

  const onChange = (value, selectedOptions) => {
    console.log('Selected values:', value);
    console.log('Selected options:', selectedOptions);
    setValue(value);
  };

  return (
    <Cascader
      checkable
      options={options}
      value={value}
      onChange={onChange}
      placeholder="Select multiple technologies"
      style={{ width: 300 }}
    />
  );
};

Show Parent Strategy

Display only parent items when all children are selected.

const ShowParentExample = () => {
  const [value, setValue] = useState([]);

  return (
    <Cascader
      checkable
      options={options}
      value={value}
      onChange={setValue}
      showCheckedStrategy={Cascader.SHOW_PARENT}
      placeholder="Show parent strategy"
    />
  );
};

Show Child Strategy

Always display individual selected items, never parent groups.

const ShowChildExample = () => {
  const [value, setValue] = useState([]);

  return (
    <Cascader
      checkable
      options={options}
      value={value}
      onChange={setValue}
      showCheckedStrategy={Cascader.SHOW_CHILD}
      placeholder="Show child strategy"
    />
  );
};

Custom Checkbox Icon

const CustomCheckboxExample = () => {
  const [value, setValue] = useState([]);

  return (
    <Cascader
      checkable={<span style={{ color: 'blue' }}>✓</span>}
      options={options}
      value={value}
      onChange={setValue}
      placeholder="Custom checkbox icon"
    />
  );
};

Controlled Multiple Selection

const ControlledMultipleExample = () => {
  const [value, setValue] = useState([
    ['tech', 'frontend', 'react'],
    ['tech', 'backend', 'nodejs']
  ]);

  const handleChange = (newValue, selectedOptions) => {
    console.log('Value changed from:', value);
    console.log('Value changed to:', newValue);
    setValue(newValue);
  };

  const handleClear = () => {
    setValue([]);
  };

  return (
    <div>
      <Cascader
        checkable
        options={options}
        value={value}
        onChange={handleChange}
        placeholder="Controlled selection"
      />
      <button onClick={handleClear} style={{ marginLeft: 8 }}>
        Clear All
      </button>
      <div style={{ marginTop: 8 }}>
        Selected: {JSON.stringify(value, null, 2)}
      </div>
    </div>
  );
};

Disabled Checkboxes

const disabledOptions = [
  {
    label: 'Skills',
    value: 'skills',
    children: [
      {
        label: 'Programming',
        value: 'programming',
        disableCheckbox: true,  // Can't select this level
        children: [
          { label: 'JavaScript', value: 'js' },
          { label: 'Python', value: 'python', disabled: true },  // Completely disabled
          { label: 'Java', value: 'java' }
        ]
      },
      {
        label: 'Design',
        value: 'design',
        children: [
          { label: 'UI Design', value: 'ui' },
          { label: 'UX Design', value: 'ux', disableCheckbox: true }
        ]
      }
    ]
  }
];

const DisabledCheckboxExample = () => {
  const [value, setValue] = useState([]);

  return (
    <Cascader
      checkable
      options={disabledOptions}
      value={value}
      onChange={setValue}
      placeholder="Some checkboxes disabled"
    />
  );
};

Multiple Selection with Search

const MultipleWithSearchExample = () => {
  const [value, setValue] = useState([]);

  return (
    <Cascader
      checkable
      options={options}
      value={value}
      onChange={setValue}
      showSearch
      autoClearSearchValue={false}  // Keep search text after selection
      placeholder="Multiple selection with search"
      style={{ width: 400 }}
    />
  );
};

Dynamic Multiple Selection

const DynamicMultipleExample = () => {
  const [options, setOptions] = useState([
    {
      label: 'Categories',
      value: 'categories',
      isLeaf: false
    }
  ]);
  const [value, setValue] = useState([]);

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

    setTimeout(() => {
      targetOption.loading = false;
      targetOption.children = [
        { label: 'Sub Category 1', value: 'sub1' },
        { label: 'Sub Category 2', value: 'sub2', disableCheckbox: true },
        { label: 'Sub Category 3', value: 'sub3' }
      ];
      setOptions([...options]);
    }, 1000);
  };

  return (
    <Cascader
      checkable
      options={options}
      value={value}
      onChange={setValue}
      loadData={loadData}
      changeOnSelect
      placeholder="Dynamic multiple selection"
    />
  );
};

Custom Display for Multiple Selection

const CustomDisplayMultipleExample = () => {
  const [value, setValue] = useState([]);

  const displayRender = (labels, selectedOptions) => {
    if (labels.length === 0) return 'Select items';
    
    if (labels.length <= 2) {
      return labels.map(labelArray => labelArray.join(' > ')).join(', ');
    }
    
    return `${labels.length} items selected`;
  };

  return (
    <Cascader
      checkable
      options={options}
      value={value}
      onChange={setValue}
      displayRender={displayRender}
      placeholder="Custom display rendering"
      style={{ width: 300 }}
    />
  );
};

Form Integration with Multiple Selection

const FormMultipleExample = () => {
  const [formData, setFormData] = useState({
    skills: [],
    interests: []
  });

  const handleSkillsChange = (value, selectedOptions) => {
    setFormData(prev => ({
      ...prev,
      skills: value
    }));
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('Form data:', formData);
  };

  return (
    <form onSubmit={handleSubmit}>
      <div style={{ marginBottom: 16 }}>
        <label>Skills:</label>
        <Cascader
          checkable
          options={skillsOptions}
          value={formData.skills}
          onChange={handleSkillsChange}
          showCheckedStrategy={Cascader.SHOW_CHILD}
          placeholder="Select your skills"
          style={{ width: '100%', marginTop: 4 }}
        />
      </div>
      
      <div style={{ marginBottom: 16 }}>
        <label>Interests:</label>
        <Cascader
          checkable
          options={interestsOptions}
          value={formData.interests}
          onChange={(value) => 
            setFormData(prev => ({ ...prev, interests: value }))
          }
          placeholder="Select your interests"
          style={{ width: '100%', marginTop: 4 }}
        />
      </div>
      
      <button type="submit">Submit</button>
    </form>
  );
};

Validation with Multiple Selection

const ValidationMultipleExample = () => {
  const [value, setValue] = useState([]);
  const [error, setError] = useState('');

  const handleChange = (newValue, selectedOptions) => {
    setValue(newValue);
    
    // Validation logic
    if (newValue.length === 0) {
      setError('Please select at least one item');
    } else if (newValue.length > 5) {
      setError('Maximum 5 items can be selected');
    } else {
      setError('');
    }
  };

  return (
    <div>
      <Cascader
        checkable
        options={options}
        value={value}
        onChange={handleChange}
        placeholder="Select 1-5 items"
        style={{ 
          width: 300,
          borderColor: error ? 'red' : undefined
        }}
      />
      {error && (
        <div style={{ color: 'red', fontSize: '12px', marginTop: 4 }}>
          {error}
        </div>
      )}
      <div style={{ marginTop: 8, fontSize: '12px', color: '#666' }}>
        Selected: {value.length}/5
      </div>
    </div>
  );
};

Install with Tessl CLI

npx tessl i tessl/npm-rc-cascader

docs

cascader.md

index.md

multiple-selection.md

panel.md

search.md

tile.json