callback to filter items before adding (#485)

* Add item custom callback

* Minor unit test updates

* Test updates, Changed callback name to more clearly distinguish it's function

* Fix description wording in cypress

* Update README

* Updated filter item callback name to be addItemFilter
This commit is contained in:
Glade 2019-02-12 09:56:21 +11:00 committed by Josh Johnson
parent 23e5e7674f
commit ba09fb00e6
6 changed files with 80 additions and 0 deletions

View File

@ -92,6 +92,7 @@ will be returned. If you target one element, that instance will be returned.
position: 'auto',
resetScrollPosition: true,
regexFilter: null,
addItemFilter: null,
shouldSort: true,
shouldSortItems: false,
sortFn: () => {...},
@ -339,6 +340,24 @@ Pass an array of objects:
**Usage:** Whether the scroll position should reset after adding an item.
### addItemFilter
**Type:** `Function` **Default:** `null`
**Input types affected:** `text`
**Usage:** A callback function that will need to return `true` for a user to successfully add an item.
**Example:**
```js
// Only adds items matching the text test
new Choices(element, {
addItemFilter: function (value) {
return (value !== 'test')
}
});
```
### regexFilter
**Type:** `Regex` **Default:** `null`

View File

@ -293,6 +293,39 @@ describe('Choices - text element', () => {
});
});
describe('custom add item callback', () => {
describe('inputting a value that satisfies the addItemFilter', () => {
const input = 'test';
it('allows me to add choice', () => {
cy.get('[data-test-hook=add-item-callback]')
.find('.choices__input--cloned')
.type(input)
.type('{enter}');
cy.get('[data-test-hook=add-item-callback]')
.find('.choices__list--multiple .choices__item')
.last()
.should($choice => {
expect($choice.text().trim()).to.equal(input);
});
});
});
describe('inputting a value that does not satisfy the callback', () => {
it('displays dropdown prompt', () => {
cy.get('[data-test-hook=add-item-callback]')
.find('.choices__input--cloned')
.type(`this is not the allowed text`)
.type('{enter}');
cy.get('[data-test-hook=add-item-callback]')
.find('.choices__list--dropdown')
.should('not.be.visible');
});
});
});
describe('disabled via attribute', () => {
it('does not allow me to input data', () => {
cy.get('[data-test-hook=disabled-via-attr]')

View File

@ -64,6 +64,11 @@
<input class="form-control" id="choices-adding-items-disabled" type="text">
</div>
<div data-test-hook="add-item-callback">
<label for="choices-add-item-callback">Callback on Add Item</label>
<input class="form-control" id="choices-add-item-callback" type="text">
</div>
<div data-test-hook="disabled-via-attr">
<label for="choices-disabled-via-attr">Disabled via attribute</label>
<input class="form-control" id="choices-disabled-via-attr" type="text" disabled>
@ -120,6 +125,12 @@
addItems: false,
});
new Choices('#choices-add-item-callback', {
addItemFilter: function (value) {
return (value !== 'test')
}
});
new Choices('#choices-disabled-via-attr');
new Choices('#choices-prepend-append', {

View File

@ -987,6 +987,19 @@ class Choices {
? this.config.uniqueItemText(value)
: this.config.uniqueItemText;
}
if (
isType('Function', this.config.addItemFilter) &&
this.config.addItemFilter(value) &&
this._isTextElement &&
this.config.addItems &&
canAddItem
) {
canAddItem = false;
notice = isType('Function', this.config.customAddItemText)
? this.config.customAddItemText(value)
: this.config.customAddItemText;
}
}
return {

View File

@ -64,6 +64,7 @@ export const DEFAULT_CONFIG = {
noChoicesText: 'No choices to choose from',
itemSelectText: 'Press to select',
uniqueItemText: 'Only unique values can be added',
customAddItemText: 'Only values matching specific conditions can be added.',
addItemText: value => `Press Enter to add <b>"${stripHTML(value)}"</b>`,
maxItemText: maxItemCount => `Only ${maxItemCount} values can be added`,
itemComparer: (choice, item) => choice === item,
@ -71,6 +72,7 @@ export const DEFAULT_CONFIG = {
includeScore: true,
},
callbackOnInit: null,
addItemFilter: null,
callbackOnCreateTemplates: null,
classNames: DEFAULT_CLASSNAMES,
};

View File

@ -82,9 +82,11 @@ describe('constants', () => {
expect(DEFAULT_CONFIG.noChoicesText).to.be.a('string');
expect(DEFAULT_CONFIG.itemSelectText).to.be.a('string');
expect(DEFAULT_CONFIG.uniqueItemText).to.be.a('string');
expect(DEFAULT_CONFIG.customAddItemText).to.be.a('string');
expect(DEFAULT_CONFIG.addItemText).to.be.a('function');
expect(DEFAULT_CONFIG.maxItemText).to.be.a('function');
expect(DEFAULT_CONFIG.fuseOptions).to.be.an('object');
expect(DEFAULT_CONFIG.addItemFilter).to.equal(null);
expect(DEFAULT_CONFIG.callbackOnInit).to.equal(null);
expect(DEFAULT_CONFIG.callbackOnCreateTemplates).to.equal(null);
});