Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add duplicate support for multi select #3786

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8.4.0
8.16.1
2 changes: 2 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# React-Select
## v1.4.0 / 2019-09-27
* support duplicate for multiselect by passing `duplicate` prop to Select component

## v1.3.0 / 2018-06-23
* [#2777](https://github.com/JedWatson/react-select/pull/2777) pass entire event to `shouldKeyDownEventCreateNewOption`
Expand Down
67 changes: 58 additions & 9 deletions dist/react-select.es.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,34 @@ var possibleConstructorReturn = function (self, call) {
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};



















var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];

return arr2;
} else {
return Array.from(arr);
}
};

var Option = function (_React$Component) {
inherits(Option, _React$Component);

Expand Down Expand Up @@ -1285,13 +1313,17 @@ var Select$1 = function (_React$Component) {
inputValue: this.handleInputValueChange(updatedValue),
isOpen: !this.props.closeOnSelect
}, function () {
var valueArray = _this3.getValueArray(_this3.props.value);
if (valueArray.some(function (i) {
return i[_this3.props.valueKey] === value[_this3.props.valueKey];
})) {
_this3.removeValue(value);
} else {
if (_this3.props.duplicate) {
_this3.addValue(value);
} else {
var valueArray = _this3.getValueArray(_this3.props.value);
if (valueArray.some(function (i) {
return i[_this3.props.valueKey] === value[_this3.props.valueKey];
})) {
_this3.removeValue(value);
} else {
_this3.addValue(value);
}
}
});
} else {
Expand Down Expand Up @@ -1338,9 +1370,24 @@ var Select$1 = function (_React$Component) {
var _this4 = this;

var valueArray = this.getValueArray(this.props.value);
this.setValue(valueArray.filter(function (i) {
return i[_this4.props.valueKey] !== value[_this4.props.valueKey];
}));

if (this.props.duplicate) {
valueArray = [].concat(toConsumableArray(valueArray));
valueArray.reverse();
var index = valueArray.findIndex(function (i) {
return i[_this4.props.valueKey] === value[_this4.props.valueKey];
});
if (index > -1) {
valueArray.splice(index, 1);
}
valueArray.reverse();
this.setValue(valueArray);
} else {
this.setValue(valueArray.filter(function (i) {
return i[_this4.props.valueKey] !== value[_this4.props.valueKey];
}));
}

this.focus();
}
}, {
Expand Down Expand Up @@ -1922,6 +1969,7 @@ Select$1.propTypes = {
deleteRemoves: PropTypes.bool, // whether delete removes an item if there is no text input
delimiter: PropTypes.string, // delimiter to use to join multiple values for the hidden field value
disabled: PropTypes.bool, // whether the Select is disabled or not
duplicate: PropTypes.bool, // whether the Select allows the same option to be selected multiple times
escapeClearsValue: PropTypes.bool, // whether escape clears the value when the menu is closed
filterOption: PropTypes.func, // method to filter a single option (option, filterString)
filterOptions: PropTypes.any, // boolean to enable default filtering or function to filter the options array ([options], filterString, [values])
Expand Down Expand Up @@ -1994,6 +2042,7 @@ Select$1.defaultProps = {
deleteRemoves: true,
delimiter: ',',
disabled: false,
duplicate: false,
escapeClearsValue: true,
filterOptions: filterOptions,
ignoreAccents: true,
Expand Down
67 changes: 58 additions & 9 deletions dist/react-select.js
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,34 @@ var possibleConstructorReturn = function (self, call) {
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};



















var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];

return arr2;
} else {
return Array.from(arr);
}
};

var Option = function (_React$Component) {
inherits(Option, _React$Component);

Expand Down Expand Up @@ -1290,13 +1318,17 @@ var Select$1 = function (_React$Component) {
inputValue: this.handleInputValueChange(updatedValue),
isOpen: !this.props.closeOnSelect
}, function () {
var valueArray = _this3.getValueArray(_this3.props.value);
if (valueArray.some(function (i) {
return i[_this3.props.valueKey] === value[_this3.props.valueKey];
})) {
_this3.removeValue(value);
} else {
if (_this3.props.duplicate) {
_this3.addValue(value);
} else {
var valueArray = _this3.getValueArray(_this3.props.value);
if (valueArray.some(function (i) {
return i[_this3.props.valueKey] === value[_this3.props.valueKey];
})) {
_this3.removeValue(value);
} else {
_this3.addValue(value);
}
}
});
} else {
Expand Down Expand Up @@ -1343,9 +1375,24 @@ var Select$1 = function (_React$Component) {
var _this4 = this;

var valueArray = this.getValueArray(this.props.value);
this.setValue(valueArray.filter(function (i) {
return i[_this4.props.valueKey] !== value[_this4.props.valueKey];
}));

if (this.props.duplicate) {
valueArray = [].concat(toConsumableArray(valueArray));
valueArray.reverse();
var index = valueArray.findIndex(function (i) {
return i[_this4.props.valueKey] === value[_this4.props.valueKey];
});
if (index > -1) {
valueArray.splice(index, 1);
}
valueArray.reverse();
this.setValue(valueArray);
} else {
this.setValue(valueArray.filter(function (i) {
return i[_this4.props.valueKey] !== value[_this4.props.valueKey];
}));
}

this.focus();
}
}, {
Expand Down Expand Up @@ -1927,6 +1974,7 @@ Select$1.propTypes = {
deleteRemoves: PropTypes.bool, // whether delete removes an item if there is no text input
delimiter: PropTypes.string, // delimiter to use to join multiple values for the hidden field value
disabled: PropTypes.bool, // whether the Select is disabled or not
duplicate: PropTypes.bool, // whether the Select allows the same option to be selected multiple times
escapeClearsValue: PropTypes.bool, // whether escape clears the value when the menu is closed
filterOption: PropTypes.func, // method to filter a single option (option, filterString)
filterOptions: PropTypes.any, // boolean to enable default filtering or function to filter the options array ([options], filterString, [values])
Expand Down Expand Up @@ -1999,6 +2047,7 @@ Select$1.defaultProps = {
deleteRemoves: true,
delimiter: ',',
disabled: false,
duplicate: false,
escapeClearsValue: true,
filterOptions: filterOptions,
ignoreAccents: true,
Expand Down
2 changes: 1 addition & 1 deletion dist/react-select.min.js

Large diffs are not rendered by default.

41 changes: 32 additions & 9 deletions lib/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in ob

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
Expand Down Expand Up @@ -713,13 +715,17 @@ var Select = function (_React$Component) {
inputValue: this.handleInputValueChange(updatedValue),
isOpen: !this.props.closeOnSelect
}, function () {
var valueArray = _this3.getValueArray(_this3.props.value);
if (valueArray.some(function (i) {
return i[_this3.props.valueKey] === value[_this3.props.valueKey];
})) {
_this3.removeValue(value);
} else {
if (_this3.props.duplicate) {
_this3.addValue(value);
} else {
var valueArray = _this3.getValueArray(_this3.props.value);
if (valueArray.some(function (i) {
return i[_this3.props.valueKey] === value[_this3.props.valueKey];
})) {
_this3.removeValue(value);
} else {
_this3.addValue(value);
}
}
});
} else {
Expand Down Expand Up @@ -766,9 +772,24 @@ var Select = function (_React$Component) {
var _this4 = this;

var valueArray = this.getValueArray(this.props.value);
this.setValue(valueArray.filter(function (i) {
return i[_this4.props.valueKey] !== value[_this4.props.valueKey];
}));

if (this.props.duplicate) {
valueArray = [].concat(_toConsumableArray(valueArray));
valueArray.reverse();
var index = valueArray.findIndex(function (i) {
return i[_this4.props.valueKey] === value[_this4.props.valueKey];
});
if (index > -1) {
valueArray.splice(index, 1);
}
valueArray.reverse();
this.setValue(valueArray);
} else {
this.setValue(valueArray.filter(function (i) {
return i[_this4.props.valueKey] !== value[_this4.props.valueKey];
}));
}

this.focus();
}
}, {
Expand Down Expand Up @@ -1350,6 +1371,7 @@ Select.propTypes = {
deleteRemoves: _propTypes2.default.bool, // whether delete removes an item if there is no text input
delimiter: _propTypes2.default.string, // delimiter to use to join multiple values for the hidden field value
disabled: _propTypes2.default.bool, // whether the Select is disabled or not
duplicate: _propTypes2.default.bool, // whether the Select allows the same option to be selected multiple times
escapeClearsValue: _propTypes2.default.bool, // whether escape clears the value when the menu is closed
filterOption: _propTypes2.default.func, // method to filter a single option (option, filterString)
filterOptions: _propTypes2.default.any, // boolean to enable default filtering or function to filter the options array ([options], filterString, [values])
Expand Down Expand Up @@ -1422,6 +1444,7 @@ Select.defaultProps = {
deleteRemoves: true,
delimiter: ',',
disabled: false,
duplicate: false,
escapeClearsValue: true,
filterOptions: _defaultFilterOptions2.default,
ignoreAccents: true,
Expand Down
17 changes: 14 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
{
"name": "react-select",
"version": "1.3.0",
"version": "1.4.0",
"description": "A Select control built with and for ReactJS",
"main": "lib/index.js",
"jsnext:main": "dist/react-select.es.js",
"module": "dist/react-select.es.js",
"style": "dist/react-select.min.css",
"author": "Jed Watson",
"contributors": [
{
"name": "Kim Yu Ng",
"email": "[email protected]"
}
],
"license": "MIT",
"repository": {
"type": "git",
Expand Down Expand Up @@ -58,7 +64,7 @@
"react-highlight-words": "^0.8.1",
"react-test-renderer": "^15.6.1",
"react-virtualized": "^9.9.0",
"react-virtualized-select": "^3.1.0",
"react-virtualized-select": "^3.1.3",
"rollup": "^0.49.2",
"rollup-plugin-babel": "^3.0.2",
"rollup-plugin-commonjs": "^8.2.0",
Expand Down Expand Up @@ -88,7 +94,12 @@
"test": "cross-env NODE_ENV=test mocha --compilers js:babel-core/register",
"precommit": "lint-staged && yarn run test"
},
"files": ["dist", "less", "lib", "scss"],
"files": [
"dist",
"less",
"lib",
"scss"
],
"keywords": [
"combobox",
"form",
Expand Down
29 changes: 24 additions & 5 deletions src/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -619,11 +619,15 @@ class Select extends React.Component {
inputValue: this.handleInputValueChange(updatedValue),
isOpen: !this.props.closeOnSelect,
}, () => {
const valueArray = this.getValueArray(this.props.value);
if (valueArray.some(i => i[this.props.valueKey] === value[this.props.valueKey])) {
this.removeValue(value);
} else {
if (this.props.duplicate) {
this.addValue(value);
} else {
const valueArray = this.getValueArray(this.props.value);
if (valueArray.some(i => i[this.props.valueKey] === value[this.props.valueKey])) {
this.removeValue(value);
} else {
this.addValue(value);
}
}
});
} else {
Expand Down Expand Up @@ -661,7 +665,20 @@ class Select extends React.Component {

removeValue (value) {
let valueArray = this.getValueArray(this.props.value);
this.setValue(valueArray.filter(i => i[this.props.valueKey] !== value[this.props.valueKey]));

if (this.props.duplicate) {
valueArray = [...valueArray];
valueArray.reverse();
const index = valueArray.findIndex((i) => (i[this.props.valueKey] === value[this.props.valueKey]));
if (index > -1) {
valueArray.splice(index, 1);
}
valueArray.reverse();
this.setValue(valueArray);
} else {
this.setValue(valueArray.filter(i => i[this.props.valueKey] !== value[this.props.valueKey]));
}

this.focus();
}

Expand Down Expand Up @@ -1205,6 +1222,7 @@ Select.propTypes = {
deleteRemoves: PropTypes.bool, // whether delete removes an item if there is no text input
delimiter: PropTypes.string, // delimiter to use to join multiple values for the hidden field value
disabled: PropTypes.bool, // whether the Select is disabled or not
duplicate: PropTypes.bool, // whether the Select allows the same option to be selected multiple times
escapeClearsValue: PropTypes.bool, // whether escape clears the value when the menu is closed
filterOption: PropTypes.func, // method to filter a single option (option, filterString)
filterOptions: PropTypes.any, // boolean to enable default filtering or function to filter the options array ([options], filterString, [values])
Expand Down Expand Up @@ -1277,6 +1295,7 @@ Select.defaultProps = {
deleteRemoves: true,
delimiter: ',',
disabled: false,
duplicate: false,
escapeClearsValue: true,
filterOptions: defaultFilterOptions,
ignoreAccents: true,
Expand Down