Skip to content

Commit

Permalink
Combobox: add select all functionality (#19539)
Browse files Browse the repository at this point in the history
  • Loading branch information
smhigley authored Sep 10, 2021
1 parent 9aa90c4 commit 27dd84d
Show file tree
Hide file tree
Showing 8 changed files with 1,242 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "feat(Combobox): add select all functionality",
"packageName": "@fluentui/react",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import * as React from 'react';
import { ComboBox, IComboBox, IComboBoxOption, IComboBoxStyles, SelectableOptionMenuItemType } from '@fluentui/react';

const options: IComboBoxOption[] = [
{ key: 'selectAll', text: 'Select All', itemType: SelectableOptionMenuItemType.SelectAll },
{ key: 'Header1', text: 'First heading', itemType: SelectableOptionMenuItemType.Header },
{ key: 'A', text: 'Option A' },
{ key: 'B', text: 'Option B' },
{ key: 'C', text: 'Option C' },
{ key: 'D', text: 'Option D' },
{ key: 'divider', text: '-', itemType: SelectableOptionMenuItemType.Divider },
{ key: 'Header2', text: 'Second heading', itemType: SelectableOptionMenuItemType.Header },
{ key: 'E', text: 'Option E' },
{ key: 'F', text: 'Option F', disabled: true },
{ key: 'G', text: 'Option G' },
{ key: 'H', text: 'Option H' },
{ key: 'I', text: 'Option I' },
{ key: 'J', text: 'Option J' },
];
// Optional styling to make the example look nicer
const comboBoxStyles: Partial<IComboBoxStyles> = { root: { maxWidth: 300 } };

// array of selectable options for convenience
const selectableOptions = options.filter(
option =>
(option.itemType === SelectableOptionMenuItemType.Normal || option.itemType === undefined) && !option.disabled,
);

export const ComboBoxSelectAllExample: React.FunctionComponent = () => {
const [selectedKeys, setSelectedKeys] = React.useState<string[]>(['A', 'D']);
const onChange = (
event: React.FormEvent<IComboBox>,
option?: IComboBoxOption,
index?: number,
value?: string,
): void => {
const selected = option?.selected;
const currentSelectedOptionKeys = selectedKeys.filter(key => key !== 'selectAll');
const selectAllState = currentSelectedOptionKeys.length === selectableOptions.length;

if (option) {
if (option?.itemType === SelectableOptionMenuItemType.SelectAll) {
selectAllState
? setSelectedKeys([])
: setSelectedKeys(['selectAll', ...selectableOptions.map(o => o.key as string)]);
} else {
const updatedKeys = selected
? [...currentSelectedOptionKeys, option!.key as string]
: currentSelectedOptionKeys.filter(k => k !== option.key);
if (updatedKeys.length === selectableOptions.length) {
updatedKeys.push('selectAll');
}
setSelectedKeys(updatedKeys);
}
}
};

return (
<div>
<ComboBox
defaultSelectedKey="C"
label="Uncontrolled multi-select ComboBox with select all"
multiSelect
options={options}
styles={comboBoxStyles}
/>

<ComboBox
label="Controlled multi-select ComboBox with select all"
multiSelect
options={options}
selectedKey={selectedKeys}
// eslint-disable-next-line react/jsx-no-bind
onChange={onChange}
styles={comboBoxStyles}
/>
</div>
);
};
7 changes: 7 additions & 0 deletions packages/react-examples/src/react/ComboBox/ComboBox.doc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ComboBoxInlineExample } from './ComboBox.Inline.Example';
import { ComboBoxTogglesExample } from './ComboBox.Toggles.Example';
import { ComboBoxControlledExample } from './ComboBox.Controlled.Example';
import { ComboBoxControlledMultiExample } from './ComboBox.ControlledMulti.Example';
import { ComboBoxSelectAllExample } from './ComboBox.SelectAll.Example';
import { ComboBoxVirtualizedExample } from './ComboBox.Virtualized.Example';
import { ComboBoxErrorHandlingExample } from './ComboBox.ErrorHandling.Example';
import { ComboBoxCustomStyledExample } from './ComboBox.CustomStyled.Example';
Expand All @@ -15,6 +16,7 @@ const ComboBoxInlineExampleCode = require('!raw-loader?esModule=false!@fluentui/
const ComboBoxTogglesExampleCode = require('!raw-loader?esModule=false!@fluentui/react-examples/src/react/ComboBox/ComboBox.Toggles.Example.tsx') as string;
const ComboBoxControlledExampleCode = require('!raw-loader?esModule=false!@fluentui/react-examples/src/react/ComboBox/ComboBox.Controlled.Example.tsx') as string;
const ComboBoxControlledMultiExampleCode = require('!raw-loader?esModule=false!@fluentui/react-examples/src/react/ComboBox/ComboBox.ControlledMulti.Example.tsx') as string;
const ComboBoxSelectAllExampleCode = require('!raw-loader?esModule=false!@fluentui/react-examples/src/react/ComboBox/ComboBox.SelectAll.Example.tsx') as string;
const ComboBoxVirtualizedExampleCode = require('!raw-loader?esModule=false!@fluentui/react-examples/src/react/ComboBox/ComboBox.Virtualized.Example.tsx') as string;
const ComboBoxErrorHandlingExampleCode = require('!raw-loader?esModule=false!@fluentui/react-examples/src/react/ComboBox/ComboBox.ErrorHandling.Example.tsx') as string;
const ComboBoxCustomStyledExampleCode = require('!raw-loader?esModule=false!@fluentui/react-examples/src/react/ComboBox/ComboBox.CustomStyled.Example.tsx') as string;
Expand Down Expand Up @@ -49,6 +51,11 @@ export const ComboBoxPageProps: IDocPageProps = {
code: ComboBoxControlledMultiExampleCode,
view: <ComboBoxControlledMultiExample />,
},
{
title: 'ComboBox with select all option',
code: ComboBoxSelectAllExampleCode,
view: <ComboBoxSelectAllExample />,
},
{
title: 'VirtualizedComboBox',
code: ComboBoxVirtualizedExampleCode,
Expand Down
Loading

0 comments on commit 27dd84d

Please sign in to comment.