Laravel/Inertia.js
검색 필터 및 더보기 구현(#Filter #Search #LoadMore)
짱구를왜말려?
2021. 11. 16. 15:16
반응형
SMALL
# What?
스크롤 유지하면서 리스트 필터링 및 더보기 구현
# Why?
요즘은 페이지 바뀌면서 스크롤 초기화되는거 지양
# How?
1. form을 watch로 검사하지 말고 각 input에 @change를 걸어 filter 메소드 호출하게 하기
2. preserveScroll : true 옵션으로 스크롤 유지하기
3. replace: true 옵션으로 페이지 히스토리를 남기지 않고 뒤로가기 시 진짜 이전 페이지로 이동하게끔 하기(안그러면 필터값 바꿀때마다의 페이지 히스토리 다 남아서 뒤로가기 시 몇번을 눌러대야함)
4. preserveState : true 옵션으로 더보기 구현 시 이전 데이터 리스트에 새로 불러온 데이터 리스트를 추가하기
<template>
<div class="subContent area-workerList">
<div class="wrap">
<div class="m-input-checkboxes type01">
<div class="m-input-checkbox type01">
<input type="checkbox" checked="checked" v-if="form.category_ids.length === 0">
<input type="checkbox" v-else>
<label for="" @click="clearCategories">전체</label>
</div>
<div class="m-input-checkbox type01" v-for="category in categories.data" :key="category.id" @change="filter">
<input type="checkbox" :id="category.id" :value="category.id" v-model.lazy="form.category_ids">
<label :for="category.id">{{ category.title }}</label>
</div>
</div>
<div class="m-input-top type01">
<div class="inputs">
<div class="m-input-select type01">
<select name="" id="" v-model.lazy="form.orderBy" @change="filter">
<option value="count_request">인기순</option>
<option value="created_at">최신순</option>
</select>
</div>
<form @submit.prevent="filter">
<div class="m-input-text type01">
<input type="text" placeholder="전문가명" v-model.lazy="form.word">
<img src="/img/search.png" alt="" class="m-input-text-deco" @click="filter">
</div>
</form>
</div>
</div>
<div class="m-empty type01" v-if="workers.data.length === 0">
데이터가 없습니다.
</div>
<workers :items="workers.data" v-else />
<div class="m-btns type01 mt-80" v-if="workers.links.next">
<button class="m-btn type01 bg-primary" @click="loadMore">더보기</button>
</div>
</div>
</div>
</template>
<script>
import Workers from "../../Components/Workers";
export default {
components: {Workers},
data() {
return {
workers: this.$page.props.workers,
categories: this.$page.props.categories,
form: this.$inertia.form({
word: this.$page.props.word,
orderBy: this.$page.props.orderBy,
category_ids: this.$page.props.category_ids,
page: 1
}),
loading: false,
}
},
methods: {
clearCategories(){
this.form.category_ids = [];
this.filter();
},
loadMore(){
if(!this.loading){
this.form.page += 1;
this.filter();
}
},
filter(){
let isLoadMore = this.workers.meta.current_page !== this.form.page;
this.loading = true;
if(!isLoadMore)
this.form.page = 1;
this.form.get("/workers", {
preserveScroll: true,
preserveState: true,
replace: true,
immediate: true,
onSuccess: (response) => {
this.loading = false;
if(isLoadMore) {
return this.workers = {
...response.props.workers,
data: [...this.workers.data, ...response.props.workers.data]
}
}
return this.workers = response.props.workers;
}
});
}
},
mounted() {
}
}
</script>
LIST