Add clearItems method + update setChoices

This commit is contained in:
Josh Johnson 2019-11-28 21:12:33 +00:00
parent 862e1a52eb
commit 9be164e2e5
4 changed files with 125 additions and 51 deletions

View file

@ -824,12 +824,6 @@ choices.setValue(['Set value 1', 'Set value 2']);
choices.disable(); choices.disable();
``` ```
### destroy();
**Input types affected:** `text`, `select-multiple`, `select-one`
**Usage:** Kills the instance of Choices, removes all event listeners and returns passed input to its initial state.
### init(); ### init();
**Input types affected:** `text`, `select-multiple`, `select-one` **Input types affected:** `text`, `select-multiple`, `select-one`
@ -838,6 +832,12 @@ choices.disable();
**Note:** This is called implicitly when a new instance of Choices is created. This would be used after a Choices instance had already been destroyed (using `destroy()`). **Note:** This is called implicitly when a new instance of Choices is created. This would be used after a Choices instance had already been destroyed (using `destroy()`).
### destroy();
**Input types affected:** `text`, `select-multiple`, `select-one`
**Usage:** Kills the instance of Choices, removes all event listeners and returns passed input to its initial state.
### highlightAll(); ### highlightAll();
**Input types affected:** `text`, `select-multiple` **Input types affected:** `text`, `select-multiple`
@ -880,7 +880,7 @@ choices.disable();
**Usage:** Hide option list dropdown (only affects select inputs). **Usage:** Hide option list dropdown (only affects select inputs).
### setChoices(choices, value, label, replaceChoices); ### setChoices(choices[, value[, label[, replaceChoices[, replaceItems]]]]);
**Input types affected:** `select-one`, `select-multiple` **Input types affected:** `select-one`, `select-multiple`
@ -902,6 +902,7 @@ example.setChoices(
'value', 'value',
'label', 'label',
false, false,
true,
); );
``` ```
@ -959,6 +960,7 @@ example.setChoices(
'value', 'value',
'label', 'label',
false, false,
true,
); );
``` ```
@ -968,6 +970,12 @@ example.setChoices(
**Usage:** Clear all choices from select **Usage:** Clear all choices from select
### clearItems();
**Input types affected:** `select-one`, `select-multiple`
**Usage:** Clear all items from select
### getValue(valueOnly) ### getValue(valueOnly)
**Input types affected:** `text`, `select-one`, `select-multiple` **Input types affected:** `text`, `select-one`, `select-multiple`

View file

@ -25,7 +25,12 @@ import {
activateChoices, activateChoices,
clearChoices, clearChoices,
} from './actions/choices'; } from './actions/choices';
import { addItem, removeItem, highlightItem } from './actions/items'; import {
addItem,
removeItem,
highlightItem,
clearItems,
} from './actions/items';
import { addGroup } from './actions/groups'; import { addGroup } from './actions/groups';
import { clearAll, resetTo, setIsLoading } from './actions/misc'; import { clearAll, resetTo, setIsLoading } from './actions/misc';
import { import {
@ -496,7 +501,8 @@ class Choices {
* @param {T} [choicesArrayOrFetcher] * @param {T} [choicesArrayOrFetcher]
* @param {string} [value = 'value'] - name of `value` field * @param {string} [value = 'value'] - name of `value` field
* @param {string} [label = 'label'] - name of 'label' field * @param {string} [label = 'label'] - name of 'label' field
* @param {boolean} [replaceChoices = false] - whether to replace of add choices * @param {boolean} [replaceChoices = false] - whether to clear existing choices
* @param {boolean} [replaceItems = false] - whether to clear existing items
* @returns {this | Promise<this>} * @returns {this | Promise<this>}
* *
* @example * @example
@ -558,6 +564,7 @@ class Choices {
value = 'value', value = 'value',
label = 'label', label = 'label',
replaceChoices = false, replaceChoices = false,
replaceItems = false,
) { ) {
if (!this.initialised) { if (!this.initialised) {
throw new ReferenceError( throw new ReferenceError(
@ -574,11 +581,14 @@ class Choices {
); );
} }
// Clear choices if needed
if (replaceChoices) { if (replaceChoices) {
this.clearChoices(); this.clearChoices();
} }
if (replaceItems) {
this.clearItems();
}
if (typeof choicesArrayOrFetcher === 'function') { if (typeof choicesArrayOrFetcher === 'function') {
// it's a choices fetcher function // it's a choices fetcher function
const fetcher = choicesArrayOrFetcher(this); const fetcher = choicesArrayOrFetcher(this);
@ -589,7 +599,9 @@ class Choices {
return new Promise(resolve => requestAnimationFrame(resolve)) return new Promise(resolve => requestAnimationFrame(resolve))
.then(() => this._handleLoadingState(true)) .then(() => this._handleLoadingState(true))
.then(() => fetcher) .then(() => fetcher)
.then(data => this.setChoices(data, value, label, replaceChoices)) .then(data =>
this.setChoices(data, value, label, replaceChoices, replaceItems),
)
.catch(err => { .catch(err => {
if (!this.config.silent) { if (!this.config.silent) {
console.error(err); console.error(err);
@ -651,6 +663,12 @@ class Choices {
return this; return this;
} }
clearItems() {
this._store.dispatch(clearItems());
return this;
}
clearStore() { clearStore() {
this._store.dispatch(clearAll()); this._store.dispatch(clearAll());

View file

@ -28,12 +28,6 @@ describe('choices', () => {
instance = null; instance = null;
}); });
const returnsInstance = () => {
it('returns this', () => {
expect(output).to.eql(instance);
});
};
describe('constructor', () => { describe('constructor', () => {
describe('config', () => { describe('config', () => {
describe('not passing config options', () => { describe('not passing config options', () => {
@ -88,6 +82,7 @@ describe('choices', () => {
`; `;
instance = new Choices('[data-choice]', { instance = new Choices('[data-choice]', {
// @ts-ignore
renderSelectedChoices: 'test', renderSelectedChoices: 'test',
}); });
@ -423,7 +418,9 @@ describe('choices', () => {
output = instance.enable(); output = instance.enable();
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('returns early', () => { it('returns early', () => {
expect(passedElementEnableSpy.called).to.equal(false); expect(passedElementEnableSpy.called).to.equal(false);
@ -481,7 +478,9 @@ describe('choices', () => {
output = instance.disable(); output = instance.disable();
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('returns early', () => { it('returns early', () => {
expect(removeEventListenersSpy.called).to.equal(false); expect(removeEventListenersSpy.called).to.equal(false);
@ -638,7 +637,9 @@ describe('choices', () => {
output = instance.hideDropdown(); output = instance.hideDropdown();
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('returns early', () => { it('returns early', () => {
expect(containerOuterCloseSpy.called).to.equal(false); expect(containerOuterCloseSpy.called).to.equal(false);
@ -735,7 +736,9 @@ describe('choices', () => {
output = instance.highlightItem(); output = instance.highlightItem();
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('returns early', () => { it('returns early', () => {
expect(passedElementTriggerEventStub.called).to.equal(false); expect(passedElementTriggerEventStub.called).to.equal(false);
@ -756,7 +759,9 @@ describe('choices', () => {
output = instance.highlightItem(item, true); output = instance.highlightItem(item, true);
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('dispatches highlightItem action with correct arguments', () => { it('dispatches highlightItem action with correct arguments', () => {
expect(storeDispatchSpy.called).to.equal(true); expect(storeDispatchSpy.called).to.equal(true);
@ -817,7 +822,9 @@ describe('choices', () => {
expect(passedElementTriggerEventStub.called).to.equal(false); expect(passedElementTriggerEventStub.called).to.equal(false);
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
}); });
}); });
}); });
@ -850,7 +857,9 @@ describe('choices', () => {
output = instance.unhighlightItem(); output = instance.unhighlightItem();
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('returns early', () => { it('returns early', () => {
expect(passedElementTriggerEventStub.called).to.equal(false); expect(passedElementTriggerEventStub.called).to.equal(false);
@ -871,7 +880,9 @@ describe('choices', () => {
output = instance.unhighlightItem(item, true); output = instance.unhighlightItem(item, true);
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('dispatches highlightItem action with correct arguments', () => { it('dispatches highlightItem action with correct arguments', () => {
expect(storeDispatchSpy.called).to.equal(true); expect(storeDispatchSpy.called).to.equal(true);
@ -932,7 +943,9 @@ describe('choices', () => {
expect(passedElementTriggerEventStub.called).to.equal(false); expect(passedElementTriggerEventStub.called).to.equal(false);
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
}); });
}); });
}); });
@ -966,7 +979,9 @@ describe('choices', () => {
storeGetItemsStub.reset(); storeGetItemsStub.reset();
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('highlights each item in store', () => { it('highlights each item in store', () => {
expect(highlightItemStub.callCount).to.equal(items.length); expect(highlightItemStub.callCount).to.equal(items.length);
@ -1004,7 +1019,9 @@ describe('choices', () => {
storeGetItemsStub.reset(); storeGetItemsStub.reset();
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('unhighlights each item in store', () => { it('unhighlights each item in store', () => {
expect(unhighlightItemStub.callCount).to.equal(items.length); expect(unhighlightItemStub.callCount).to.equal(items.length);
@ -1027,7 +1044,9 @@ describe('choices', () => {
instance._store.dispatch.reset(); instance._store.dispatch.reset();
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('dispatches clearChoices action', () => { it('dispatches clearChoices action', () => {
expect(storeDispatchStub.lastCall.args[0]).to.eql({ expect(storeDispatchStub.lastCall.args[0]).to.eql({
@ -1050,7 +1069,9 @@ describe('choices', () => {
instance._store.dispatch.reset(); instance._store.dispatch.reset();
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('dispatches clearAll action', () => { it('dispatches clearAll action', () => {
expect(storeDispatchStub.lastCall.args[0]).to.eql({ expect(storeDispatchStub.lastCall.args[0]).to.eql({
@ -1075,7 +1096,9 @@ describe('choices', () => {
instance._store.dispatch.reset(); instance._store.dispatch.reset();
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
describe('text element', () => { describe('text element', () => {
beforeEach(() => { beforeEach(() => {
@ -1211,7 +1234,9 @@ describe('choices', () => {
output = instance.setValue(values); output = instance.setValue(values);
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('returns early', () => { it('returns early', () => {
expect(setChoiceOrItemStub.called).to.equal(false); expect(setChoiceOrItemStub.called).to.equal(false);
@ -1224,7 +1249,9 @@ describe('choices', () => {
output = instance.setValue(values); output = instance.setValue(values);
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('sets each value', () => { it('sets each value', () => {
expect(setChoiceOrItemStub.callCount).to.equal(2); expect(setChoiceOrItemStub.callCount).to.equal(2);
@ -1252,7 +1279,9 @@ describe('choices', () => {
output = instance.setChoiceByValue([]); output = instance.setChoiceByValue([]);
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('returns early', () => { it('returns early', () => {
expect(findAndSelectChoiceByValueStub.called).to.equal(false); expect(findAndSelectChoiceByValueStub.called).to.equal(false);
@ -1272,7 +1301,9 @@ describe('choices', () => {
output = instance.setChoiceByValue(value); output = instance.setChoiceByValue(value);
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('sets each choice with same value', () => { it('sets each choice with same value', () => {
expect(findAndSelectChoiceByValueStub.called).to.equal(true); expect(findAndSelectChoiceByValueStub.called).to.equal(true);
@ -1289,7 +1320,9 @@ describe('choices', () => {
output = instance.setChoiceByValue(values); output = instance.setChoiceByValue(values);
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('sets each choice with same value', () => { it('sets each choice with same value', () => {
expect(findAndSelectChoiceByValueStub.callCount).to.equal(2); expect(findAndSelectChoiceByValueStub.callCount).to.equal(2);
@ -1509,7 +1542,9 @@ describe('choices', () => {
output = instance.removeHighlightedItems(); output = instance.removeHighlightedItems();
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('removes each highlighted item in store', () => { it('removes each highlighted item in store', () => {
expect(removeItemStub.callCount).to.equal(2); expect(removeItemStub.callCount).to.equal(2);
@ -1521,7 +1556,9 @@ describe('choices', () => {
output = instance.removeHighlightedItems(true); output = instance.removeHighlightedItems(true);
}); });
returnsInstance(output); it('returns this', () => {
expect(output).to.eql(instance);
});
it('triggers event with item value', () => { it('triggers event with item value', () => {
expect(triggerChangeStub.callCount).to.equal(2); expect(triggerChangeStub.callCount).to.equal(2);
@ -1533,6 +1570,7 @@ describe('choices', () => {
describe('setChoices', () => { describe('setChoices', () => {
let clearChoicesStub; let clearChoicesStub;
let clearItemsStub;
let addGroupStub; let addGroupStub;
let addChoiceStub; let addChoiceStub;
let containerOuterRemoveLoadingStateStub; let containerOuterRemoveLoadingStateStub;
@ -1560,11 +1598,13 @@ describe('choices', () => {
beforeEach(() => { beforeEach(() => {
clearChoicesStub = stub(); clearChoicesStub = stub();
clearItemsStub = stub();
addGroupStub = stub(); addGroupStub = stub();
addChoiceStub = stub(); addChoiceStub = stub();
containerOuterRemoveLoadingStateStub = stub(); containerOuterRemoveLoadingStateStub = stub();
instance.clearChoices = clearChoicesStub; instance.clearChoices = clearChoicesStub;
instance.clearItems = clearItemsStub;
instance._addGroup = addGroupStub; instance._addGroup = addGroupStub;
instance._addChoice = addChoiceStub; instance._addChoice = addChoiceStub;
instance.containerOuter.removeLoadingState = containerOuterRemoveLoadingStateStub; instance.containerOuter.removeLoadingState = containerOuterRemoveLoadingStateStub;
@ -1595,7 +1635,7 @@ describe('choices', () => {
instance._isSelectElement = true; instance._isSelectElement = true;
}); });
it('throws', () => { it('throws a TypeError', () => {
expect(() => expect(() =>
instance.setChoices(choices, null, 'label', false), instance.setChoices(choices, null, 'label', false),
).to.throw(TypeError, /value/i); ).to.throw(TypeError, /value/i);
@ -1643,16 +1683,8 @@ describe('choices', () => {
}); });
}); });
describe('passing an empty array with a true replaceChoices flag', () => {
it('choices are cleared', () => {
instance._isSelectElement = true;
instance.setChoices([], value, label, true);
expect(clearChoicesStub.called).to.equal(true);
});
});
describe('passing an empty array with a false replaceChoices flag', () => { describe('passing an empty array with a false replaceChoices flag', () => {
it('choices stay the same', () => { it('does not clear existing choices', () => {
instance._isSelectElement = true; instance._isSelectElement = true;
instance.setChoices([], value, label, false); instance.setChoices([], value, label, false);
expect(clearChoicesStub.called).to.equal(false); expect(clearChoicesStub.called).to.equal(false);
@ -1660,18 +1692,32 @@ describe('choices', () => {
}); });
describe('passing true replaceChoices flag', () => { describe('passing true replaceChoices flag', () => {
it('choices are cleared', () => { it('clears existing choices', () => {
instance.setChoices(choices, value, label, true); instance.setChoices(choices, value, label, true);
expect(clearChoicesStub.called).to.equal(true); expect(clearChoicesStub.called).to.equal(true);
}); });
}); });
describe('passing false replaceChoices flag', () => { describe('passing false replaceChoices flag', () => {
it('choices are not cleared', () => { it('clears existing choices are not cleared', () => {
instance.setChoices(choices, value, label, false); instance.setChoices(choices, value, label, false);
expect(clearChoicesStub.called).to.equal(false); expect(clearChoicesStub.called).to.equal(false);
}); });
}); });
describe('passing true replaceItems flag', () => {
it('clears existing items', () => {
instance.setChoices(choices, value, label, true, true);
expect(clearItemsStub.called).to.equal(true);
});
});
describe('passing false replaceItems flag', () => {
it('does not clears existing items', () => {
instance.setChoices(choices, value, label, true, false);
expect(clearItemsStub.called).to.equal(false);
});
});
}); });
}); });
}); });

4
types/index.d.ts vendored
View file

@ -933,7 +933,8 @@ export default class Choices {
* *
* @param {string} [value = 'value'] - name of `value` field * @param {string} [value = 'value'] - name of `value` field
* @param {string} [label = 'label'] - name of 'label' field * @param {string} [label = 'label'] - name of 'label' field
* @param {boolean} [replaceChoices = false] - whether to replace of add choices * @param {boolean} [replaceChoices = false] - whether to clear existing choices
* @param {boolean} [replaceItems = false] - whether to clear existing items
* *
* @example * @example
* ```js * ```js
@ -996,6 +997,7 @@ export default class Choices {
value?: string, value?: string,
label?: string, label?: string,
replaceChoices?: boolean, replaceChoices?: boolean,
replaceItems?: boolean,
): T extends object[] ? this : Promise<this>; ): T extends object[] ? this : Promise<this>;
/** /**