WEBOPIXEL

Vue.jsでリストをモーダルウィンドウから選択する

Posted: 2017.09.29 / Category: javascript / Tag: 

Vue.jsでリストをモーダルウィンドウを開き、項目を選択できるような動きをやってみます。

Sponsored Link

Vue cli インストールした Vue 2.2 を使用しています。

文字だとわかり難いのでイメージはこんな感じです。

SelectList.vue

SelectListという名称でメインの機能を作成します。

components/SelectList.vue

<template>
	<div>
		<div>
			<ul class="item-list is-border">
				<li v-for="item in selectItems">
					{{ item.name }}
					<a class="delete-btn" @click="onDeleteItem(item)">X</a>
				</li>
			</ul>
			<button class="btn" @click="isModal = true">アイテム選択</button>
		</div>
		<transition name="modal" v-if="isModal">
			<div class="overlay" @click="isModal = false">
				<div class="panel" @click.stop>
					<h3>アイテムを選択してください</h3>
					<div class="scroll-box">
						<ul class="item-list">
							<li v-for="item in filteredItems" @click="onSlectItem(item)">
								{{ item.name }}
							</li>
						</ul>
					</div>
					<button class="btn" @click="isModal = false">閉じる</button>
				</div>
			</div>
		</transition>
	</div>
</template>
<script>
	export default {
		props: ['setSelectItems'],
		mounted() {
			for (var i=1; i<=100; i++) {
				this.items.push({
					id: i,
					name: 'item' + i
				});
			}
		},
		data() {
			return {
				isModal: false,     // Modak表示フラグ
				items: [],          // すべてのアイテム
				selectItems: this.setSelectItems    // 選択したアイテム
			}
		},
		methods: {
			// アイテムを選択
			onSlectItem(item) {
				this.selectItems.push({
					'id': parseInt(item.id),
					'name': item.name
				});
				this.isModal = false;
			},
			// アイテムを削除
			onDeleteItem(item) {
				let index = this.selectItems.indexOf(item);
				this.selectItems.splice(index, 1);
			}
		},
		computed: {
			// 選択されているオプションは非表示
			filteredItems() {
				let data = this.items;
				let selects = this.selectItems;
	
				data = data.filter(function (row) {
					for (var i=0; i<selects.length; i++) {
						if (selects[i].id == row['id']) {
							return false;
							break;
						}
					}
					return true;
				});
				return data;
			}
		}
	}
</script>
<style lang="scss">
.overlay {
    background: rgba(0, 0, 0, .8);
    position: fixed;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 900;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;

}

.panel {
    width: 600px;
    height: 400px;
    background: #fff;
    padding: 20px;

    h3 {
        margin-bottom: 10px;
    }
}

.scroll-box {
    height: 300px;
    overflow-y: auto;
    margin-bottom: 20px;
    border: solid 1px #bbb;
}
.item-list {
    list-style: none;
    padding: 0;

    &.is-border {
        border: solid 1px #bbb;
        margin-bottom: 20px;
    }

    li {
        border-top: solid 1px #bbb;
        margin-top: -1px;
        padding: 10px;
        display: flex;
        justify-content: space-between;

        &:first-child {
            border-top: none;
        }
    }
}
.btn {
    width: 100%;
    padding: 15px;
    border: none;
    background: #eee;
}
</style>
3行目
setSelectItemsは選択しているアイテムの配列です。propsでコンポーネントの呼び出し元からデータを受け取ります。
5~10行目
仮なのでforitemのデータを生成してます。本来ならどこかから読み込む感じになるかと思います。
19〜33行目
methodsは追加と削除だけです。
36〜50行目
選択しているアイテム(selectItems)は表示させなくしています。

App.vue

先ほど作成したSelectList.vueApp.vueで呼び出します。

<template>
    <div id="app">
        <select-list :setSelectItems="selectItems"></select-list>
    </div>
</template>
import SelectList from "./components/SelectList.vue";
		
export default {
	name: 'app',
	data() {
		return {
			selectItems: [
				{
					id: 2,
					name: 'item2'
				},{
					id: 4,
					name: 'item4'
				}
			]
		}
	},
	components: {
		SelectList
	},
}

選択したいアイテムの変数を作成してsetSelectItemsに渡すだけですね。