Skip to content

Commit 678755e

Browse files
committed
Added new prop: keepSelectionOrder
1 parent 01e6017 commit 678755e

File tree

7 files changed

+164
-21
lines changed

7 files changed

+164
-21
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class Example extends Component {
105105
| `responsiveHeight` | `string` | 400px | Responsive height of the wrapping component, can send percent for example: `70%` |
106106
| `withGrouping` | `boolean` | false | Your items will be grouped by the group prop values - see "item grouping" section below |
107107
| `showSelectedItemsSearch` | `boolean` | false | toggle to show search option in detination list. |
108+
| `keepSelectionOrder` | `boolean` | false | keep selection order in the detination list |
108109
| `searchSelectedItemsValue` | `string` | | The value of the search field for destination list. |
109110
| `searchSelectedItemsChanged` | `function` | | Function to handle the change of search field for destination list. Accepts value as a single argument. |
110111
| `selectedItemsFilterFunction` | `function` | based on label | Is the same as filterFunction by default to filter items based on the search query in destination list. |

src/components/multi_select.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export class MultiSelect extends PureComponent {
2626
showSearch: PropTypes.bool,
2727
showSelectAll: PropTypes.bool,
2828
showSelectedItems: PropTypes.bool,
29+
keepSelectionOrder: PropTypes.bool,
2930
searchIcon: PropTypes.string,
3031
deleteIcon: PropTypes.string,
3132
searchRenderer: PropTypes.func,
@@ -55,7 +56,8 @@ export class MultiSelect extends PureComponent {
5556
loaderRenderer: Loader,
5657
withGrouping: false,
5758
generateClassName: defaultGenerateClassName,
58-
showSelectedItemsSearch: false
59+
showSelectedItemsSearch: false,
60+
keepSelectionOrder: false
5961
};
6062

6163
calculateHeight() {
@@ -112,7 +114,8 @@ export class MultiSelect extends PureComponent {
112114
searchSelectedItemsValue,
113115
filterSelectedItems,
114116
filteredSelectedItems,
115-
isLocked
117+
isLocked,
118+
keepSelectionOrder
116119
} = this.props;
117120
const calculatedHeight = this.calculateHeight();
118121
const selectedIds = selectedItems.map(item => item.id);
@@ -151,6 +154,7 @@ export class MultiSelect extends PureComponent {
151154
withGrouping={withGrouping}
152155
listRenderer={listRenderer}
153156
isLocked={isLocked}
157+
keepSelectionOrder={keepSelectionOrder}
154158
/>
155159
)}
156160
{!loading && showSelectedItems && (

src/components/multi_select_state.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ const withMultiSelectState = WrappedComponent =>
115115
}
116116

117117
selectItem(event, id) {
118-
const { items } = this.props;
118+
const { items, keepSelectionOrder } = this.props;
119119
const { selectedItems, firstItemShiftSelected } = this.state;
120120
if (!selectedItems.find(item => item.id === id)) {
121121
if (event.shiftKey && firstItemShiftSelected !== undefined) {
@@ -125,15 +125,25 @@ const withMultiSelectState = WrappedComponent =>
125125
const index = items.findIndex(item => item.id === id);
126126
this.setState({ firstItemShiftSelected: index });
127127
}
128-
this.setNewItemsBySelectItem(id, items, selectedItems);
128+
this.setNewItemsBySelectItem(
129+
id,
130+
items,
131+
selectedItems,
132+
keepSelectionOrder
133+
);
129134
}
130135
} else {
131136
this.unselectItems([id]);
132137
}
133138
}
134139

135-
setNewItemsBySelectItem(id, items, selectedItems) {
136-
const newSelectedItems = getNewSelectedItems(id, items, selectedItems);
140+
setNewItemsBySelectItem(id, items, selectedItems, keepSelectionOrder) {
141+
const newSelectedItems = getNewSelectedItems(
142+
id,
143+
items,
144+
selectedItems,
145+
keepSelectionOrder
146+
);
137147
const newFilteredSelectedItems = this.getNewFilteredSelectedItems(
138148
newSelectedItems
139149
);

src/components/multi_select_state_utils.js

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,26 @@ export const getMinMaxIndexes = (currentIndex, firstItemShiftSelected) =>
4040
export const isWithin = (index, { minIndex, maxIndex }) =>
4141
index >= minIndex && index <= maxIndex;
4242

43-
export const getNewSelectedItems = (itemId, items, selectedItems) => {
44-
const sourceItems = items.filter(
45-
item => item.id === itemId || findItem(item, selectedItems)
46-
);
47-
const destinationItems = selectedItems.filter(
48-
selectedItem => !findItem(selectedItem, items)
49-
);
50-
return [...destinationItems, ...sourceItems];
43+
export const getNewSelectedItems = (
44+
itemId,
45+
items,
46+
selectedItems,
47+
keepSelectionOrder
48+
) => {
49+
let alreadySelectedItems = [];
50+
let sourceItems = [];
51+
let destinationItems = [];
52+
53+
if (keepSelectionOrder) {
54+
// In order to keep selection order on the list,
55+
// First, iterate threw already selectedItems
56+
alreadySelectedItems = selectedItems.filter(item => findItem(item, items));
57+
sourceItems = items.filter(item => item.id === itemId);
58+
} else {
59+
sourceItems = items.filter(
60+
item => item.id === itemId || findItem(item, selectedItems)
61+
);
62+
}
63+
64+
return [...alreadySelectedItems, ...sourceItems];
5165
};

stories/multi-select.stories.js

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@ storiesOf("React Multi Select", module)
8080
);
8181
})
8282
)
83+
.add(
84+
"with keep selection order",
85+
withReadme(Readme, () => {
86+
return (
87+
<ReactMultiSelect
88+
items={utils.items}
89+
loading={boolean("Loading", false)}
90+
onChange={action("onChange")}
91+
showSearch={boolean("Show search", true)}
92+
showSelectAll={boolean("Show select all", true)}
93+
keepSelectionOrder={boolean("keep selection order", true)}
94+
/>
95+
);
96+
})
97+
)
8398
.add(
8499
"With some of the items disabled",
85100
withReadme(Readme, () => {
@@ -363,15 +378,12 @@ storiesOf("React Multi Select", module)
363378
withReadme(Readme, () => {
364379
class SelectedItemsController extends React.Component {
365380
SINGLE_ITEM = [{ id: 1, label: "Item 1" }];
366-
MULTI_ITEMS = [
367-
{ id: 2, label: "Item 2" },
368-
{ id: 4, label: "Item 4" }
369-
]
381+
MULTI_ITEMS = [{ id: 2, label: "Item 2" }, { id: 4, label: "Item 4" }];
370382

371383
constructor(props) {
372384
super(props);
373385
this.state = {
374-
selectedItems: this.SINGLE_ITEM,
386+
selectedItems: this.SINGLE_ITEM
375387
};
376388
}
377389

@@ -384,7 +396,10 @@ storiesOf("React Multi Select", module)
384396
type="button"
385397
onClick={() => {
386398
this.setState({
387-
selectedItems: this.state.selectedItems.length > 1 ? this.SINGLE_ITEM : this.MULTI_ITEMS
399+
selectedItems:
400+
this.state.selectedItems.length > 1
401+
? this.SINGLE_ITEM
402+
: this.MULTI_ITEMS
388403
});
389404
}}
390405
/>

0 commit comments

Comments
 (0)