mirror of
https://github.com/Choices-js/Choices.git
synced 2026-03-14 14:45:47 +01:00
Merge pull request #1358 from samuelhwilliams/search-render-selected-choices
Allow selected options to be hidden when searching
This commit is contained in:
commit
51f77558a9
8 changed files with 118 additions and 1 deletions
|
|
@ -1,5 +1,10 @@
|
|||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Features
|
||||
- Add `searchRenderSelectedChoices` configuration option to control whether selected choices appear in search results for select-multiple inputs. Defaults to `true` (backward compatible behavior). Set to `false` to hide selected choices from search results.
|
||||
|
||||
## [11.2.0]
|
||||
|
||||
### Features
|
||||
|
|
|
|||
18
README.md
18
README.md
|
|
@ -177,6 +177,7 @@ import "choices.js/public/assets/styles/choices.css";
|
|||
prependValue: null,
|
||||
appendValue: null,
|
||||
renderSelectedChoices: 'auto',
|
||||
searchRenderSelectedChoices: true,
|
||||
loadingText: 'Loading...',
|
||||
noResultsText: 'No results found',
|
||||
noChoicesText: 'No choices to choose from',
|
||||
|
|
@ -671,6 +672,23 @@ For backward compatibility, `<option value="">This is a placeholder</option>` an
|
|||
|
||||
**Usage:** Whether selected choices should be removed from the list. By default choices are removed when they are selected in multiple select box. To always render choices pass `always`.
|
||||
|
||||
### searchRenderSelectedChoices
|
||||
|
||||
**Type:** `Boolean` **Default:** `true'`
|
||||
|
||||
**Input types affected:** `select-multiple`
|
||||
|
||||
**Usage:** Whether selected choices should be removed from the list during search.
|
||||
|
||||
**Example:**
|
||||
|
||||
```js
|
||||
// Hide selected choices from search results
|
||||
const example = new Choices(element, {
|
||||
searchRenderSelectedChoices: false,
|
||||
});
|
||||
```
|
||||
|
||||
### loadingText
|
||||
|
||||
**Type:** `String` **Default:** `Loading...`
|
||||
|
|
|
|||
|
|
@ -500,6 +500,29 @@
|
|||
</script>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="search-hide-selected">
|
||||
<label for="choices-search-hide-selected">Search hide selected</label>
|
||||
<select
|
||||
class="form-control"
|
||||
name="choices-search-hide-selected"
|
||||
id="choices-search-hide-selected"
|
||||
multiple
|
||||
>
|
||||
<option value="Choice 1">Choice 1</option>
|
||||
<option value="Choice 2">Choice 2</option>
|
||||
<option value="Choice 3">Choice 3</option>
|
||||
<option value="Choice 4">Choice 4</option>
|
||||
</select>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
new Choices('#choices-search-hide-selected', {
|
||||
allowHTML: false,
|
||||
searchRenderSelectedChoices: false,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<div data-test-hook="placeholder-via-option-value">
|
||||
<label for="choices-placeholder-via-option-value"
|
||||
>Placeholder via empty option value</label
|
||||
|
|
|
|||
|
|
@ -970,7 +970,10 @@ class Choices {
|
|||
const renderableChoices = (choices: ChoiceFull[]): ChoiceFull[] =>
|
||||
choices.filter(
|
||||
(choice) =>
|
||||
!choice.placeholder && (isSearching ? !!choice.rank : config.renderSelectedChoices || !choice.selected),
|
||||
!choice.placeholder &&
|
||||
(isSearching
|
||||
? (config.searchRenderSelectedChoices || !choice.selected) && !!choice.rank
|
||||
: config.renderSelectedChoices || !choice.selected),
|
||||
);
|
||||
|
||||
const showLabel = config.appendGroupInSearch && isSearching;
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ export const DEFAULT_CONFIG: Options = {
|
|||
prependValue: null,
|
||||
appendValue: null,
|
||||
renderSelectedChoices: 'auto',
|
||||
searchRenderSelectedChoices: true,
|
||||
loadingText: 'Loading...',
|
||||
noResultsText: 'No results found',
|
||||
noChoicesText: 'No choices to choose from',
|
||||
|
|
|
|||
|
|
@ -480,6 +480,15 @@ export interface Options {
|
|||
*/
|
||||
renderSelectedChoices: 'auto' | 'always' | boolean;
|
||||
|
||||
/**
|
||||
* Whether selected choices should be removed from the list during search.
|
||||
*
|
||||
* **Input types affected:** select-multiple
|
||||
*
|
||||
* @default false;
|
||||
*/
|
||||
searchRenderSelectedChoices: boolean;
|
||||
|
||||
/**
|
||||
* The text that is shown whilst choices are being populated via AJAX.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -651,6 +651,47 @@ describe(`Choices - select multiple`, () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('search hide selected', () => {
|
||||
const testId = 'search-hide-selected';
|
||||
|
||||
describe('selecting choices and searching', () => {
|
||||
test('selected choices do not appear in search results', async ({ page, bundle }) => {
|
||||
const suite = new SelectTestSuit(page, bundle, testUrl, testId);
|
||||
await suite.startWithClick();
|
||||
|
||||
await suite.getChoiceWithText('Choice 1').click();
|
||||
await suite.expectedItemCount(1);
|
||||
|
||||
await suite.typeText('Choice');
|
||||
await suite.expectVisibleDropdown();
|
||||
|
||||
await expect(suite.choices.filter({ hasText: 'Choice 1' })).toHaveCount(0);
|
||||
|
||||
await expect(suite.choices.filter({ hasText: 'Choice 2' })).toHaveCount(1);
|
||||
await expect(suite.choices.filter({ hasText: 'Choice 3' })).toHaveCount(1);
|
||||
await expect(suite.choices.filter({ hasText: 'Choice 4' })).toHaveCount(1);
|
||||
});
|
||||
|
||||
test('selecting multiple choices hides all from search', async ({ page, bundle }) => {
|
||||
const suite = new SelectTestSuit(page, bundle, testUrl, testId);
|
||||
await suite.startWithClick();
|
||||
|
||||
await suite.getChoiceWithText('Choice 1').click();
|
||||
await suite.getChoiceWithText('Choice 2').click();
|
||||
await suite.expectedItemCount(2);
|
||||
|
||||
await suite.typeText('Choice');
|
||||
await suite.expectVisibleDropdown();
|
||||
|
||||
await expect(suite.choices.filter({ hasText: 'Choice 1' })).toHaveCount(0);
|
||||
await expect(suite.choices.filter({ hasText: 'Choice 2' })).toHaveCount(0);
|
||||
|
||||
await expect(suite.choices.filter({ hasText: 'Choice 3' })).toHaveCount(1);
|
||||
await expect(suite.choices.filter({ hasText: 'Choice 4' })).toHaveCount(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
[
|
||||
{
|
||||
name: 'empty option value',
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ describe('choices', () => {
|
|||
searchEnabled: false,
|
||||
closeDropdownOnSelect: true,
|
||||
renderSelectedChoices: false,
|
||||
searchRenderSelectedChoices: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -68,6 +69,7 @@ describe('choices', () => {
|
|||
searchEnabled: false,
|
||||
closeDropdownOnSelect: true,
|
||||
renderSelectedChoices: false,
|
||||
searchRenderSelectedChoices: true,
|
||||
...config,
|
||||
});
|
||||
});
|
||||
|
|
@ -115,6 +117,21 @@ describe('choices', () => {
|
|||
expect(instance.config.renderSelectedChoices).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('passing the searchRenderSelectedChoices config option with false', () => {
|
||||
it('keeps searchRenderSelectedChoices as false', () => {
|
||||
document.body.innerHTML = `
|
||||
<select data-choice multiple></select>
|
||||
`;
|
||||
|
||||
instance = new Choices('[data-choice]', {
|
||||
allowHTML: true,
|
||||
searchRenderSelectedChoices: false,
|
||||
});
|
||||
|
||||
expect(instance.config.searchRenderSelectedChoices).to.equal(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue