livewire alpine fusejs.io 사용한 select 만들기
Updated on
저번에 계속해서 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:돌체}]
이런식임.
일단, 20000개 데이터 렉 하나도 없이 엄청 빠르게 잘 작동됨.
그 이상도 가능할 것 같은데 ??? 일단 여기까지, limit 으로 보여지는거 개수도 설정 할 수 있음.
초이스 js 의 문제점은 일단 디자인 수정이 조금 어려웠던거랑 생각보다 순수 바닐라스크립트라서 렉이 없을 줄 알았는데, 렉이 있더라. 그게 좀 아쉬웠음.
그러다보니까 직접 livewire 에서 alpine.js 로 만든듯…
fusejs 는 정말 가볍고 빠른 엄청난 물건이 틀림없는듯…
fusejs 라이브러리를 통해서 간단하게 값을 도출할 수 있었던거 같다 !
코드 리팩토링은 나중에 할 수 잇음 해야갯다…