WEBOPIXEL

Vue.js + Vuexでストアの絞り込み検索(フィルター)

Posted: 2018.11.21 / Category: javascript / Tag: 

LaravelでSPA(タスク管理アプリ)作る日記5回目です。今回はVuexのStateに対して絞り込み検索を実装します。

Sponsored Link

使用環境
vue: ^2.5.7
vuex: ^3.0.1
dayjs”: ^1.7.7
element-ui: ^2.4.8

この記事は下記の続きです。

Laravel + JWTAuth + Vue.js でAPIログイン認証の実装
Laravel + Vue.js にVuexを導入する
LaravelでCRUD APIを作成する
Laravel+Vue.js+VuexでフロントのCRUDを作成

完成イメージはこんな感じです。

ストアの作成

ストアから見ていきます。
tasksステートは実際はサーバーから受け取るデータなので実際は空ですが、データ構造は次のようになっています。

resources/js/store/modules/task.js

const state = {
	tasks: [
		{
			id: 1,
			title: "はじめてのタスク",	// タイトル
			state_id: 0,	// 状態ID
			user_id: 1,		// ユーザーID
			due_at: "2018-11-14 15:00:00",	// 期日
			created_at: "2018-10-02 14:28:19",	// 作成日
			updated_at: "2018-11-05 22:41:04"	// 編集日
		},
		{
			...
		}
	],
	filterQuery: {}	// 検索パラメータ
};

今回は、テキスト入力でのtitle検索、セレクトボックスでのstate_idの検索、デイトピッカーでのcreated_atの検索をします。

ステートには検索情報を入れるためのfilterQueryを作成します。

次にミューテーションです。
引数を展開してステートに入れるだけの関数を作成します。

const mutations = {
	// ...
	setFilterQuery(state, filterQuery) {
		state.filterQuery = {...filterQuery};
	}
};

ストアの最後はゲッターです。
ここにフィルター処理を書きます。

登録日(Date)の処理に今回はDayjsというライブラリを使用します。
NPMでインストールしておきましょう。

npm install dayjs --save

詳細は下記記事もご覧ください。

軽量の日付操作JavaScriptライブラリ「Day.js」
import dayjs from 'dayjs';
		
const getters = {
	filteredTasks (state) {
		let data = state.tasks;

		// タイトルの検索
		if (state.filterQuery.title !== "") {
			data = data.filter(function (row) {
				return row['title'].indexOf(state.filterQuery.title) !== -1;
			});
		}

		// 状態の検索
		if (state.filterQuery.state_id !== "") {
			data = data.filter(function (row) {
				return row['state_id'] === state.filterQuery.state_id;
			});
		}

		// 作成日で検索
		if (state.filterQuery.created_at !== null) {
			const queryData = dayjs(state.filterQuery.created_at).format('YYYY-MM-DD');
			data = data.filter(function (row) {
				return queryData === dayjs(row.created_at).format('YYYY-MM-DD');
			});
		}

		return data;
	}
};

titleは文字列検索なのでindexOfを使用して文字列が含まれるか判定します。
state_idは配列番号での検索なので、単純に数値がマッチしているかです。
created_atに関しては今回は時間を除く日付だけで検索したいので、日付フォーマットして検索してます。
また Element UI を使用している場合、未入力はnullになるのでここだけ入力条件がnullになります。
検索条件が追加された場合でも基本このパターンで追記していくだけで大丈夫そうです。

今回は取得したデータの検索のみなので、アクションは使用しません。

コンポーネントの編集

作成したストアをコンポーネントで使用してみましょう。

dataにローカルでアクセスする用のfilterQueryを作成します。

resources/js/components/pages/Task.vue

data() {
	return {
		filterQuery: {
			title: "",
			state_id: "",
			created_at: null
		},
		status: [{
			name: '未着手',
			color: '#999'
		},{
			name: '実行中',
			color: '#E6A23C'
		}, {
			name: '完了',
			color: '#67C23A'
		}],
	}
},

computedに作成したゲッターメソッドを登録。

computed: {
	...mapGetters('task', [
		'filteredTasks'
	]),
},

mountedsetFilterQueryを実行して、filterQueryの初期値が入るようにします。

mounted() {
	this.setFilterQuery(this.filterQuery);
},

methodsにはテンプレートから実行されるhandleChangeQueryを作成します。
ミューテーションで作成したsetFilterQueryを実行するだけですね。

methods: {
	handleChangeQuery() {
		this.setFilterQuery(this.filterQuery);
	},
},

コンポーネントのテンプレート部分です。
Element UI を使用しているのでちょっと特殊ではありますが、基本的にはv-modelfilterQueryを指定して、@changehandleChangeQueryを指定します。

<el-form :inline="true" class="search-form">
	<el-form-item>
		<el-input
			v-model="filterQuery.title"
			placeholder="タイトル"
			@change="handleChangeQuery"
			clearable></el-input>
	</el-form-item>

	<el-form-item>
		<el-select
			v-model="filterQuery.state_id"
			placeholder="状態"
			@change="handleChangeQuery"
			clearable>
			<el-option
				v-for="(item, index) in status"
				:key="index"
				:label="item.name"
				:value="index">
			</el-option>
		</el-select>
	</el-form-item>

	<el-form-item>
		<el-date-picker
			v-model="filterQuery.created_at"
			type="date"
			placeholder="登録日"
			@change="handleChangeQuery">
		</el-date-picker>
	</el-form-item>
</el-form>

最後にリスト表示している部分にゲッターのfilteredTasksを指定します。
Element UI ではテーブルはel-tableです。:dataに指定します。

<el-table :data="filteredTasks" :row-key="row => row.id" border stripe>
ここまでのソースコードはGithubに載せてあります。
LaravelTodoSPA