Skip to content

Commit

Permalink
feat: add showSearchClear option to clear search input (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
ghiscoding authored Nov 5, 2023
1 parent 8731387 commit 32de6f2
Show file tree
Hide file tree
Showing 8 changed files with 335 additions and 3 deletions.
2 changes: 2 additions & 0 deletions demo/src/app-routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import Options30 from './options/options30';
import Options31 from './options/options31';
import Options32 from './options/options32';
import Options33 from './options/options33';
import Options34 from './options/options34';
import Methods01 from './methods/methods01';
import Methods02 from './methods/methods02';
import Methods03 from './methods/methods03';
Expand Down Expand Up @@ -122,6 +123,7 @@ export const exampleRouting = [
{ name: 'options31', view: '/src/options/options31.html', viewModel: Options31, title: 'Use Select Option as Label' },
{ name: 'options32', view: '/src/options/options32.html', viewModel: Options32, title: 'Sanitizer' },
{ name: 'options33', view: '/src/options/options33.html', viewModel: Options33, title: 'Classes' },
{ name: 'options34', view: '/src/options/options34.html', viewModel: Options34, title: 'Show Search Clear' },
],
},
{
Expand Down
1 change: 1 addition & 0 deletions demo/src/examples/example10.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default class Example {
this.ms1 = multipleSelect('#select', {
filter: true,
data,
showSearchClear: true,
}) as MultipleSelectInstance;
}

Expand Down
214 changes: 214 additions & 0 deletions demo/src/options/options34.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
<div class="row mb-2">
<div class="col-md-12 title-desc">
<h2 class="bd-title">
Show Search Clear
<span class="float-end links">
Code <span class="fa fa-link"></span>
<span class="small">
<a
target="_blank"
href="https://github.com/ghiscoding/multiple-select-vanilla/blob/main/demo/src/options/options34.html"
>html</a
>
|
<a target="_blank" href="https://github.com/ghiscoding/multiple-select-vanilla/blob/main/demo/src/options/options34.ts"
>ts</a
>
</span>
</span>
</h2>
<div class="demo-subtitle">Use <code>showSearchClear</code> to show the clear icon to empty the search filter input.</div>
</div>
</div>

<div>
<div class="mb-3 row">
<label class="col-sm-2"> Single Select </label>

<div class="col-sm-10">
<select class="full-width" data-test="select1">
<option value="1">abc</option>
<option value="2">bcd</option>
<option value="3">cde</option>
<option value="4">def</option>
<option value="5">efg</option>
<option value="6">fgh</option>
<option value="7">ghi</option>
<option value="8">hij</option>
<option value="9">ijk</option>
<option value="10">jkl</option>
<option value="11">klm</option>
<option value="12">lmn</option>
<option value="13">mno</option>
<option value="14">nop</option>
<option value="15">opq</option>
<option value="16">pqr</option>
<option value="17">qrs</option>
<option value="18">rst</option>
<option value="19">stu</option>
<option value="20">tuv</option>
<option value="21">uvw</option>
<option value="22">vwx</option>
<option value="23">wxy</option>
<option value="24">xyz</option>
<option value="25">123</option>
<option value="26">234</option>
<option value="27">345</option>
<option value="28">456</option>
<option value="29">567</option>
<option value="30">678</option>
<option value="31">789</option>
</select>
</div>
</div>

<div class="mb-3 row">
<label class="col-sm-2"> Single Group </label>

<div class="col-sm-10">
<select class="full-width" data-test="select2">
<optgroup label="Group 10">
<option value="1">000</option>
<option value="2">111</option>
<option value="3">222</option>
</optgroup>
<optgroup label="Group 11">
<option value="4">333</option>
<option value="5">444</option>
<option value="6">555</option>
</optgroup>
<optgroup label="Group 12">
<option value="7">666</option>
<option value="8">777</option>
<option value="9">888</option>
<option value="10">999</option>
</optgroup>
<optgroup label="Group 20">
<option value="11">210</option>
<option value="12">321</option>
<option value="13">432</option>
</optgroup>
<optgroup label="Group 21">
<option value="14">543</option>
<option value="15">654</option>
<option value="16">765</option>
</optgroup>
<optgroup label="Group 22">
<option value="17">876</option>
<option value="18">987</option>
<option value="19">098</option>
</optgroup>
<optgroup label="Group 30">
<option value="20">012</option>
<option value="21">123</option>
<option value="22">234</option>
</optgroup>
<optgroup label="Group 31">
<option value="23">345</option>
<option value="24">456</option>
<option value="25">567</option>
</optgroup>
<optgroup label="Group 32">
<option value="26">678</option>
<option value="27">789</option>
<option value="28">890</option>
</optgroup>
</select>
</div>
</div>

<div class="mb-3 row">
<label class="col-sm-2"> Basic Select </label>

<div class="col-sm-10">
<select multiple="multiple" class="full-width" data-test="select3">
<option value="1">abc</option>
<option value="2">bcd</option>
<option value="3">cde</option>
<option value="4">def</option>
<option value="5">efg</option>
<option value="6">fgh</option>
<option value="7">ghi</option>
<option value="8">hij</option>
<option value="9">ijk</option>
<option value="10">jkl</option>
<option value="11">klm</option>
<option value="12">lmn</option>
<option value="13">mno</option>
<option value="14">nop</option>
<option value="15">opq</option>
<option value="16">pqr</option>
<option value="17">qrs</option>
<option value="18">rst</option>
<option value="19">stu</option>
<option value="20">tuv</option>
<option value="21">uvw</option>
<option value="22">vwx</option>
<option value="23">wxy</option>
<option value="24">xyz</option>
<option value="25">123</option>
<option value="26">234</option>
<option value="27">345</option>
<option value="28">456</option>
<option value="29">567</option>
<option value="30">678</option>
<option value="31">789</option>
</select>
</div>
</div>

<div class="mb-3 row">
<label class="col-sm-2"> Group Select </label>

<div class="col-sm-10">
<select multiple="multiple" class="full-width" data-test="select4">
<optgroup label="Group 10">
<option value="1">000</option>
<option value="2">111</option>
<option value="3">222</option>
</optgroup>
<optgroup label="Group 11">
<option value="4">333</option>
<option value="5">444</option>
<option value="6">555</option>
</optgroup>
<optgroup label="Group 12">
<option value="7">666</option>
<option value="8">777</option>
<option value="9">888</option>
<option value="10">999</option>
</optgroup>
<optgroup label="Group 20">
<option value="11">210</option>
<option value="12">321</option>
<option value="13">432</option>
</optgroup>
<optgroup label="Group 21">
<option value="14">543</option>
<option value="15">654</option>
<option value="16">765</option>
</optgroup>
<optgroup label="Group 22">
<option value="17">876</option>
<option value="18">987</option>
<option value="19">098</option>
</optgroup>
<optgroup label="Group 30">
<option value="20">012</option>
<option value="21">123</option>
<option value="22">234</option>
</optgroup>
<optgroup label="Group 31">
<option value="23">345</option>
<option value="24">456</option>
<option value="25">567</option>
</optgroup>
<optgroup label="Group 32">
<option value="26">678</option>
<option value="27">789</option>
<option value="28">890</option>
</optgroup>
</select>
</div>
</div>
</div>
18 changes: 18 additions & 0 deletions demo/src/options/options34.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { multipleSelect, MultipleSelectInstance } from 'multiple-select-vanilla';

export default class Example {
ms: MultipleSelectInstance[] = [];

mount() {
this.ms = multipleSelect('select', {
filter: true,
showSearchClear: true,
}) as MultipleSelectInstance[];
}

unmount() {
// destroy ms instance(s) to avoid DOM leaks
this.ms.forEach((m) => m.destroy());
this.ms = [];
}
}
18 changes: 17 additions & 1 deletion lib/src/MultipleSelectInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export class MultipleSelectInstance {
protected fromHtml = false;
protected choiceElm!: HTMLButtonElement;
protected closeElm?: HTMLElement | null;
protected closeSearchElm?: HTMLElement | null;
protected filterText = '';
protected updateData: any[] = [];
protected data?: Array<OptionRowData | OptGroupRowData> = [];
Expand Down Expand Up @@ -384,6 +385,10 @@ export class MultipleSelectInstance {
placeholder: this.options.filterPlaceholder || '🔎︎',
})
);

if (this.options.showSearchClear) {
this.filterParentElm.appendChild(createDomElement('span', { className: 'icon-close' }));
}
}

if (this.options.selectAll && !this.options.single) {
Expand Down Expand Up @@ -663,6 +668,7 @@ export class MultipleSelectInstance {
this._bindEventService.unbind(this.disableItemElms);
this._bindEventService.unbind(this.noResultsElm);

this.closeSearchElm = this.filterParentElm?.querySelector('.icon-close');
this.searchInputElm = this.dropElm.querySelector<HTMLInputElement>('.ms-search input');
this.selectAllElm = this.dropElm.querySelector<HTMLInputElement>(`input[data-name="${this.selectAllName}"]`);
this.selectGroupElms = this.dropElm.querySelectorAll<HTMLInputElement>(
Expand Down Expand Up @@ -702,7 +708,6 @@ export class MultipleSelectInstance {
}

this._bindEventService.bind(this.parentElm, 'keydown', ((e: KeyboardEvent) => {
// esc key
if (e.code === 'Escape' && !this.options.keepOpen) {
this.close();
this.choiceElm.focus();
Expand All @@ -720,6 +725,17 @@ export class MultipleSelectInstance {
}) as EventListener);
}

if (this.closeSearchElm) {
this._bindEventService.bind(this.closeSearchElm, 'click', ((e: MouseEvent) => {
e.preventDefault();
if (this.searchInputElm) {
this.searchInputElm.value = '';
this.searchInputElm.focus();
}
this.filter();
}) as EventListener);
}

if (this.searchInputElm) {
this._bindEventService.bind(this.searchInputElm, 'keydown', ((e: KeyboardEvent) => {
// Ensure shift-tab causes lost focus from filter as with clicking away
Expand Down
3 changes: 3 additions & 0 deletions lib/src/interfaces/multipleSelectOption.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ export interface MultipleSelectOption extends MultipleSelectLocale {
/** Show a clear button, defaults to false */
showClear?: boolean;

/** Show a clear button on the filter search input, defaults to false */
showSearchClear?: boolean;

/** Display the OK button at bottom of the list when using multiple selection to easily close the drop, defaults to false. */
showOkButton?: boolean;

Expand Down
23 changes: 21 additions & 2 deletions lib/src/styles/multiple-select.scss
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@
}

.ms-search {
display: inline-block;
display: flex;
box-sizing: border-box;
position: relative;
white-space: nowrap;
width: 100%;
Expand All @@ -198,7 +199,25 @@
margin: var(--ms-search-input-margin, $ms-search-input-margin);
}

box-sizing: border-box;
span.icon-close {
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
right: 18px;
height: 100%;
width: 18px;

&:before {
content: '×';
color: #888;
font-weight: bold;
}

&:hover:before {
color: #333;
}
}
}

.ms-drop {
Expand Down
Loading

0 comments on commit 32de6f2

Please sign in to comment.