Continuation from pt.3
Implementation
3. components/DrillDown.vue
Create files
touch components/DrillDown.vue
mkdir -p __mock__/api/drillDown
touch __mock__/api/drillDown/dummy.json
touch __mock__/api/drillDown/GET.js
touch store/drillDown.js
Set form data to DrillDown.vue in DrillDownSearch.vue
vim pages/DrillDownSearch.vue
▼
// pages/DrillDownSearch.vue
<template>
<v-app>
<div>
<v-btn @click="open" block>
Components Button
</v-btn>
<ConfirmDialog ref="confirm">
<DrillDown :firstItems="firstItems" :initial-item="initialItem"></DrillDown>
</ConfirmDialog>
</div>
</v-app>
</template>
<script>
// ...
import DrillDown from '../components/DrillDown.vue'
export default {
components: { Button, ConfirmDialog, DrillDown },
data() {
return {
firstItems: [1, 2, 3],
initialItem: {
option1: 1,
option2: '',
option3: ''
},
isDialogOpened: false
}
},
// ...
}
</script>
▼
vim components/DrillDown.vue
▼
// components/DrillDown.vue
<template>
<div>
<v-container fluid>
<v-select v-for="(value, key) in initialItem"
:key="key"
:value="value"
:items="getOption(key)"
:label="key"
outlined
></v-select>
</v-container>
</div>
</template>
<script>
export default {
props: {
initialItem: {
type: Object,
default: {}
},
firstItems: {
type: Array,
default: []
}
},
computed: {
option1() {
if (this.firstItems.length === 0) return []
return [{ text: '選択してください', value: ''}, ...this.firstItems]
},
option2() {
return [{ text: '選択してください', value: ''}]
},
option3() {
return [{ text: '選択してください', value: ''}]
}
},
methods: {
getOption(key) {
switch (key) {
case 'option1':
return this.option1
case 'option2':
return this.option2
case 'option3':
return this.option3
}
}
}
}
</script>
Prepare dummy data
vim __mock__/api/drillDown/dummy.json
▼
// __mock__/api/drillDown/dummy.json
{
"1": [
{"text": "1-1"},
{"text": "1-2"},
{"text": "1-3"}
],
"1-1": [
{"text": "1-1-1"},
{"text": "1-1-2"},
{"text": "1-1-3"}
],
"1-2": [
{"text": "1-2-1"},
{"text": "1-2-2"},
{"text": "1-2-3"}
],
"1-3": [
{"text": "1-3-1"},
{"text": "1-3-2"},
{"text": "1-3-3"}
],
"2": [
{"text": "2-1"},
{"text": "2-2"},
{"text": "2-3"}
],
"2-1": [
{"text": "2-1-1"},
{"text": "2-1-2"},
{"text": "2-1-3"}
],
"2-2": [
{"text": "2-2-1"},
{"text": "2-2-2"},
{"text": "2-2-3"}
],
"2-3": [
{"text": "2-3-1"},
{"text": "2-3-2"},
{"text": "2-3-3"}
],
"3": [
{"text": "3-1"},
{"text": "3-2"},
{"text": "3-3"}
],
"3-1": [
{"text": "3-1-1"},
{"text": "3-1-2"},
{"text": "3-1-3"}
],
"3-2": [
{"text": "3-2-1"},
{"text": "3-2-2"},
{"text": "3-2-3"}
],
"3-3": [
{"text": "3-3-1"},
{"text": "3-3-2"},
{"text": "3-3-3"}
]
}
Prepare get function (just return dummy data)
vim __mock__/api/drillDown/GET.js
▼
// __mock__/api/drillDown/GET.js
const dummyData = require('./dummy.json')
function get(request, response) {
return response.json({
http_status: 200,
success: true,
dummyData
})
}
module.exports = get
Prepare action function (just fetch dummy data)
vim store/drillDown.js
▼
// store/drillDown.js
export const actions = {
async fetch() {
const path = `/drillDown`
return this.$axios.$get(path)
.then(res => {
const { drillDown } = res
})
}
}
Use action in DrillDown.vue
vim pages/DrillDownSearch.vue
▼
// pages/DrillDownSearch.vue
<template>
<v-app>
<div>
<v-btn @click="open" block>
Components Button
</v-btn>
<ConfirmDialog ref="confirm">
<DrillDown :firstItems="firstItems" :initial-item="initialItem" :path="path"></DrillDown>
</ConfirmDialog>
</div>
</v-app>
</template>
<script>
const PATH = 'drillDown/fetch'
// ...
export default {
// ...
data() {
return {
// ...
isDialogOpened: false,
path: PATH
}
},
// ...
}
</script>
▼
vim components/DrillDown.vue
▼
// components/DrillDown.vue
// ...
<script>
export default {
props: {
// ...
firstItems: {
type: Array,
default: []
},
path: {
type: String,
default: ''
}
},
computed: {
// ...
},
mounted() {
this.prepareOption()
},
methods: {
async prepareOption() {
await this.$store.dispatch(this.path, {
option1: this.initialItem.option1
})
},
// ...
}
}
</script>
Return options according to post data
vim components/DrillDown.vue
▼
// components/DrillDown.vue
// ...
<script>
export default {
// ...
methods: {
async prepareOption() {
// ...
await this.$store.dispatch(this.path, {
option1: this.initialItem.option1,
option2: this.initialItem.option2
})
},
// ...
}
}
</script>
▼
vim store/drillDown.js
▼
// store/drillDown.js
export const actions = {
async fetch({ commit }, params) {
const path = `/drillDown`
return this.$axios.$get(path, {params: params})
.then(res => {
const { drillDown } = res
})
}
}
▼
vim __mock__/api/drillDown/GET.js
▼
// __mock__/api/drillDown/GET.js
// ...
function get(request, response) {
const drillDown = makeResDataBy(request.query)
return response.json({
// ...
drillDown
})
}
function makeResDataBy(params) {
const res = {
option2: null,
option3: null
}
const reqKeys = Object.keys(params)
const resKeys = Object.keys(res)
const reqLength = Object.keys(params).length
const reqKey = reqKeys[reqLength - 1]
const resKey = resKeys[reqLength - 1]
const reqValue = params[reqKey]
res[resKey] = dummyData[reqValue]
return res
}
module.exports = get
Store fetch data
vim store/drillDown.js
▼
// store/drillDown.js
export const state = () => ({
option2: null,
option3: null
})
export const mutations = {
SET(state, obj) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
if (obj[keys[i]]) {
state[keys[i]] = obj[keys[i]]
break
}
}
}
}
export const actions = {
async fetch({ commit }, params) {
// ...
return this.$axios.$get(path, {params: params})
.then(res => {
// ...
commit('SET', drillDown)
})
}
}
Set initial option and value
vim components/DrillDown.vue
▼
// components/DrillDown.vue
<template>
<div>
<v-container fluid>
<v-select v-for="(value, key) in initialItem"
:key="key"
:value="value"
:items="getOption(key)"
:label="key"
:disabled="isDisabled(key)"
outlined
></v-select>
</v-container>
</div>
</template>
<script>
export default {
// ...
data: () => ({
item1: '',
item2: '',
item3: '',
canSelect: {
option1: true,
option2: false,
option3: false,
},
isSetInitialOption: false
}),
computed: {
// ...
option2() {
if (!this.$store.state.drillDown) return []
const option = this.$store.state.drillDown.option2
return option
? [{ text: '選択してください', value: ''}, ...option]
: [{ text: '選択してください', value: ''}]
},
option3() {
if (!this.$store.state.drillDown) return []
const option = this.$store.state.drillDown.option3
return option
? [{ text: '選択してください', value: ''}, ...option]
: [{ text: '選択してください', value: ''}]
}
},
methods: {
async prepareOption() {
// ...
this.$nextTick(() => {
this.setInitialValue()
})
},
setInitialValue() {
this.item1 = this.initialItem.option1 ? this.initialItem.option1 : ''
this.item2 = this.initialItem.option2 ? this.initialItem.option2 : ''
this.item3 = this.initialItem.option3 ? this.initialItem.option3 : ''
this.$nextTick(() => {
this.isSetInitialOption = true
})
},
// ...
isDisabled(key) {
return !this.canSelect[key]
}
}
}
</script>
Watch items and Update item according to new value
vim components/DrillDown.vue
▼
// components/DrillDown.vue
<template>
<div>
<v-container fluid>
<v-select v-for="(value, key) in initialItem"
:key="key"
:value="value"
:items="getOption(key)"
:label="key"
:disabled="isDisabled(key)"
@input="newv => updateItem(newv, value, key)"
outlined
></v-select>
</v-container>
</div>
</template>
<script>
export default {
// ...
methods: {
// ...
updateItem(newv, value, key) {
switch (key) {
case 'option1':
this.item1 = newv
break
case 'option2':
this.item2 = newv
break
case 'option3':
this.item3 = newv
break
}
},
// ...
},
watch: {
item1(newv) {
if (!this.isSetInitialOption) return
this.canSelect['option3'] = false
this.item2 = ''
this.item3 = ''
if (newv === '') {
this.canSelect['option2'] = false
return
}
this.$store.dispatch(this.path, {
option1: newv
})
.then(() => {
if (this.$store.state.drillDown.option2) {
this.canSelect['option2'] = true
} else {
this.canSelect['option2'] = false
}
})
.catch(err => {
console.log('/drillDown: ', err)
this.isError = true
})
},
item2(newv) {
if (!this.isSetInitialOption) return
this.item3 = ''
if (newv === '') {
this.canSelect['option3'] = false
return
}
this.$store.dispatch(this.path, {
option1: this.item1,
option2: newv
})
.then(() => {
if (this.$store.state.drillDown.option3) {
this.canSelect['option3'] = true
} else {
this.canSelect['option3'] = false
}
})
.catch(err => {
console.log('/drillDown: ', err)
this.isError = true
})
}
}
</script>
▼
vim pages/DrillDownSearch.vue
▼
// pages/DrillDownSearch.vue
// ...
<script>
// ...
export default {
// ...
data() {
return {
// ...
isResoleved: false,
// ...
}
},
computed: {
item1() {
return this.isResoleved ? this.$refs.drillDown.item1 : this.initialItem.option1
},
item2() {
return this.isResoleved ? this.$refs.drillDown.item2 : this.initialItem.option2
},
item3() {
return this.isResoleved ? this.$refs.drillDown.item3 : this.initialItem.option3
}
},
methods: {
async open() {
// ...
if (await this.$refs.confirm.open()) {
// ...
this.isResoleved = true
} else {
// ...
}
}
}
}
</script>