Livewire、Alpine、fusejs.ioを使ったselectの作成
この前からずっとselectを作っていたけど…\ 作業に成功した… まあ…整理すればもっとすっきりできるかもしれないけど、とりあえずここまで…。やることが山積みなので、 以前使っていたselect2も修正してみないと。検索もできて、あらかじめlistも表示されるものを… マウスでもキーボードでも操作できる。\ ちなみに
GGAMI
この前からずっとselectを作っていたけど…
作業に成功した…

この前からずっとselectを作っていたけど…\ 作業に成功した… まあ…整理すればもっとすっきりできるかもしれないけど、とりあえずここまで…。やることが山積みなので、 以前使っていたselect2も修正してみないと。検索もできて、あらかじめlistも表示されるものを… マウスでもキーボードでも操作できる。\ ちなみに
この前からずっとselectを作っていたけど…
作業に成功した…

<div class="mt-1">
<div x-data="{
open: false,
select: null,
result: [],
input: '',
input_index: null,
search() {
this.result = fuse.search(this.input, { limit: 25 });
this.input_index = 0;
$el.querySelector(`#list`).scrollTop = 0;
},
selected() {
this.open = false;
if(this.input !== '') {
this.select = this.result[this.input_index].item.id;
}
},
move(idx) {
id = this.input_index + idx
if(this.result[id] !== undefined) {
this.input_index = id
el = $el.querySelector(`[data-key='${this.input_index}']`);
pos = getRelativePos(el);
if(pos.next !== undefined) {
el.parentNode.scrollTop = pos.next;
}
}
},
filterName(key) {
filter = $component('collection').company_list.find(el => el.id === key);
if(filter === undefined) return null;
return filter.name;
},
resetData(type=false) {
this.result = []; this.input = ''; this.input_index = null;
if(type === true) { this.select = null; }
}
}"
x-init="
() => {
fuse = new Fuse($component('collection').company_list, { includeMatches: true, threshold: 0.1, keys: ['name'] })
}
$watch('open', value => { $nextTick(() => { if(value) { $refs.input.focus(); } else { resetData(); $refs.select.focus(); } }); })"
x-on:click.away="open = false"
@close-event.window="resetData(true)"
>
<div class="relative">
<input type="text" class="shadow-sm focus:ring-gray-500 focus:border-gray-500 block w-full text-xs sm:text-sm border-gray-300 bg-gray-50 cursor-pointer"
placeholder="선택"
readonly
:class="{ 'rounded-t-md' : open , 'rounded-md' : !open }"
x-ref="select"
x-on:click="open = !open"
x-bind:value="filterName(select)"
x-on:keydown.enter.prevent="open = !open">
<div class="flex-col absolute w-full bg-white"
x-show="open"
x-cloak>
<input type="text" class="shadow-sm focus:ring-gray-500 focus:border-gray-500 block w-full text-xs sm:text-sm border-gray-300"
placeholder="내용 입력"
x-model="input"
x-ref="input"
x-on:input.debounce.250="search();"
x-on:keydown.enter.prevent="selected()"
x-on:keydown.arrow-up.prevent="move(-1)"
x-on:keydown.arrow-down.prevent="move(1)"
>
<div class="max-h-60 overflow-auto border-2 border-t-0"
id="list">
<template x-for="(it, index) in result" :key="index">
<div class="p-2 bg-white border-gray-300 focus:border-gray-500 cursor-pointer"
:class="{'bg-gray-200' : index === input_index}"
x-on:mouseenter.prevent="input_index = index"
x-on:click="selected()"
x-text="it.item.name"
x-bind:data-key="index"></div>
</template>
</div>
</div>
</div>
</div>
</div>まあ…整理すればもっとすっきりできるかもしれないけど、とりあえずここまで…。やることが山積みなので、
以前使っていたselect2も修正してみないと。検索もできて、あらかじめlistも表示されるものを…
マウスでもキーボードでも操作できる。
ちなみに、データは [{id:1,name:까미},{id:2,name:돌체}]
こんな感じ。
とりあえず、データが20,000件あってもまったくラグがなく、すごく速く動作する。
それ以上もいけそうだけど?? とりあえずここまで。limitで表示する件数も設定できる。
Choice.jsの問題点は、まずデザインの変更が少し難しかったことと、思ったより純粋なバニラJavaScriptだったのでラグはないと思っていたのに、ラグがあったこと。その点が少し残念だった。
それで、LivewireでAlpine.jsを使って自分で作ったみたい…
Fuse.jsは本当に軽くて速い、すごいものに違いないと思う…
Fuse.jsライブラリを使って、簡単に値を導き出せた気がする!
コードのリファクタリングは、あとでできるならやらないと…