mand-mobile/components/picker/index.vue

286 lines
6.2 KiB
Vue

<template>
<div
class="md-picker"
:class="{'with-popup': !isView}"
>
<template v-if="isView">
<md-picker-column
ref="pickerColumn"
:data="data"
:default-value="defaultValue"
:default-index="defaultIndex"
:invalid-index="invalidIndex"
:cols="cols"
@initialed="$emit('initialed')"
@change="$_onPickerChange"
></md-picker-column>
</template>
<template v-else>
<md-popup
v-model="isPickerShow"
position="bottom"
@beforeShow="$_onPickerBeforeShow"
@show="$_onPickerShow"
@hide="$_onPickerHide"
prevent-scroll
>
<md-popup-title-bar
:title="title"
:ok-text="okText"
:cancel-text="cancelText"
@confirm="$_onPickerConfirm"
@cancel="$_onPickerCancel"
></md-popup-title-bar>
<md-picker-column
ref="pickerColumn"
:data="data"
:default-value="defaultValue"
:default-index="defaultIndex"
:invalid-index="invalidIndex"
:cols="cols"
@initialed="$emit('initialed')"
@change="$_onPickerChange"
></md-picker-column>
</md-popup>
</template>
</div>
</template>
<script>
import Popup from '../popup'
import PopTitleBar from '../popup/title-bar'
import PickerColumn from './picker-column'
import cascadePicker from './cascade'
import {compareObjects} from '../_util'
export default {
name: 'md-picker',
components: {
[Popup.name]: Popup,
[PopTitleBar.name]: PopTitleBar,
[PickerColumn.name]: PickerColumn,
},
props: {
value: {
type: Boolean,
default: false,
},
data: {
type: Array,
default() {
return []
},
},
cols: {
type: Number,
default: 1,
},
defaultValue: {
type: Array,
default() {
return []
},
},
defaultIndex: {
type: Array,
default() {
const arr = new Array(this.cols)
for (let i = 0, len = arr.length; i < len; i++) {
arr[i] = 0
}
return arr
},
},
invalidIndex: {
type: Array,
default() {
return []
},
},
isCascade: {
type: Boolean,
default: false,
},
isView: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
okText: {
type: String,
default: '确认',
},
cancelText: {
type: String,
default: '取消',
},
},
data() {
return {
isPickerShow: false,
}
},
computed: {
column() {
return this.$refs['pickerColumn']
},
isScrollInitialed() {
return this.column.isScrollInitialed
},
},
watch: {
value(val) {
this.isPickerShow = val
val && this.$_initPicker()
},
isPickerShow(val) {
if (!val) {
this.$emit('input', val)
}
},
data: {
handler(val, oldVal) {
this.$_resetPickerColumn(val, oldVal)
},
deep: true,
},
defaultIndex: {
handler(val, oldVal) {
this.$_resetPickerColumn(val, oldVal)
},
deep: true,
},
},
mounted() {
this.$_initPicker()
if (this.isView) {
this.$nextTick(() => {
this.column.refresh()
})
}
},
methods: {
// MARK: events handler
$_initPicker() {
if (!this.isView && this.value) {
this.isPickerShow = this.value
}
this.column.inheritPickerApi(this, ['refresh'])
},
$_initPickerColumn() {
/* istanbul ignore if */
if (!this.isCascade) {
return
}
const defaultIndexOfFirstColumn = this.defaultIndex[0] || 0
this.$nextTick(() => {
cascadePicker(this.column, {
currentLevel: 0,
maxLevel: this.cols,
values: this.data[0] ? this.data[0][defaultIndexOfFirstColumn] || [] : [],
defaultIndex: this.defaultIndex,
})
this.$nextTick(() => {
this.column.refresh()
})
})
},
$_resetPickerColumn(val, oldVal) {
if (!compareObjects(val, oldVal)) {
this.$_initPickerColumn()
}
},
$_onPickerConfirm() {
const column = this.column
const columnValues = column.getColumnValues()
let isScrolling = false
column.scrollers.forEach(scroller => {
/* istanbul ignore next */
if (
scroller._isAnimating !== false ||
scroller._isDecelerating !== false ||
scroller._isDragging !== false ||
scroller._isGesturing !== false
) {
isScrolling = true
return false
}
})
if (!isScrolling) {
this.isPickerShow = false
this.$emit('confirm', columnValues)
}
},
$_onPickerCancel() {
this.isPickerShow = false
this.$emit('cancel')
},
$_onPickerChange(columnIndex, itemIndex, values) {
/* istanbul ignore next */
if (this.isCascade) {
cascadePicker(
this.column,
{
currentLevel: columnIndex,
maxLevel: this.cols,
values,
},
() => {
// reinitiate columns after the changing column
this.column.refresh(null, columnIndex + 1)
},
)
}
/* istanbul ignore next */
this.$emit('change', columnIndex, itemIndex, values)
},
$_onPickerBeforeShow() {
/* istanbul ignore next */
if (!this.isScrollInitialed) {
this.$nextTick(() => {
this.column.refresh()
})
}
},
$_onPickerHide() {
this.$emit('hide')
},
$_onPickerShow() {
this.$emit('show')
},
refresh() {
this.column.isScrollInitialed = false
/**
* Manual call 'column.refresh' only when picker is in-view or popup is show,
* otherwise 'column.refresh' will be called at popup's 'onBerforeShow' automatically
*/
if (this.isView || this.isPickerShow) {
this.column.refresh.apply(this.column, arguments)
}
},
},
}
</script>
<style lang="stylus">
.md-picker
width 100%
&.with-popup .md-popup
z-index picker-zindex !important
</style>