add Transfer component
add Transfer component
This commit is contained in:
parent
306e3f74e8
commit
77f7bb9533
15 changed files with 519 additions and 6 deletions
186
src/components/transfer/transfer.vue
Normal file
186
src/components/transfer/transfer.vue
Normal file
|
@ -0,0 +1,186 @@
|
|||
<template>
|
||||
<div :class="classes">
|
||||
<List
|
||||
v-ref:left
|
||||
:prefix-cls="prefixCls + '-list'"
|
||||
:data="leftData"
|
||||
:render-format="renderFormat"
|
||||
:checked-keys.sync="leftCheckedKeys"
|
||||
:valid-keys-count.sync="leftValidKeysCount"
|
||||
:style="listStyle"
|
||||
:title="titles[0]"
|
||||
:filterable="filterable"
|
||||
:filter-placeholder="filterPlaceholder"
|
||||
:filter-method="filterMethod"
|
||||
:not-found-text="notFoundText">
|
||||
<slot></slot>
|
||||
</List><Operation
|
||||
:prefix-cls="prefixCls"
|
||||
:operations="operations"
|
||||
:left-active="leftValidKeysCount > 0"
|
||||
:right-active="rightValidKeysCount > 0"></Operation><List
|
||||
v-ref:right
|
||||
:prefix-cls="prefixCls + '-list'"
|
||||
:data="rightData"
|
||||
:render-format="renderFormat"
|
||||
:checked-keys.sync="rightCheckedKeys"
|
||||
:valid-keys-count.sync="rightValidKeysCount"
|
||||
:style="listStyle"
|
||||
:title="titles[1]"
|
||||
:filterable="filterable"
|
||||
:filter-placeholder="filterPlaceholder"
|
||||
:filter-method="filterMethod"
|
||||
:not-found-text="notFoundText">
|
||||
<slot></slot>
|
||||
</List>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import List from './list.vue';
|
||||
import Operation from './operation.vue';
|
||||
|
||||
const prefixCls = 'ivu-transfer';
|
||||
|
||||
export default {
|
||||
components: { List, Operation },
|
||||
props: {
|
||||
data: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
renderFormat: {
|
||||
type: Function,
|
||||
default (item) {
|
||||
return item.label || item.key;
|
||||
}
|
||||
},
|
||||
targetKeys: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
selectedKeys: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
listStyle: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
titles: {
|
||||
type: Array,
|
||||
default () {
|
||||
return ['源列表', '目的列表']
|
||||
}
|
||||
},
|
||||
operations: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
filterable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
filterPlaceholder: {
|
||||
type: String,
|
||||
default: '请输入搜索内容'
|
||||
},
|
||||
filterMethod: {
|
||||
type: Function,
|
||||
default (data, query) {
|
||||
const type = ('label' in data) ? 'label' : 'key';
|
||||
return data[type].indexOf(query) > -1;
|
||||
}
|
||||
},
|
||||
notFoundText: {
|
||||
type: String,
|
||||
default: '列表为空'
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
prefixCls: prefixCls,
|
||||
leftData: [],
|
||||
rightData: [],
|
||||
leftCheckedKeys: [],
|
||||
rightCheckedKeys: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classes () {
|
||||
return [
|
||||
`${prefixCls}`
|
||||
]
|
||||
},
|
||||
leftValidKeysCount () {
|
||||
return this.getValidKeys('left').length;
|
||||
},
|
||||
rightValidKeysCount () {
|
||||
return this.getValidKeys('right').length;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getValidKeys (direction) {
|
||||
return this[`${direction}Data`].filter(data => !data.disabled && this[`${direction}CheckedKeys`].indexOf(data.key) > -1).map(data => data.key);
|
||||
},
|
||||
splitData (init = false) {
|
||||
this.leftData = [...this.data];
|
||||
this.rightData = [];
|
||||
if (this.targetKeys.length > 0) {
|
||||
this.targetKeys.forEach((targetKey) => {
|
||||
this.rightData.push(
|
||||
this.leftData.filter((data, index) => {
|
||||
if (data.key === targetKey) {
|
||||
this.leftData.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})[0]);
|
||||
});
|
||||
}
|
||||
if (init) {
|
||||
this.splitSelectedKey();
|
||||
}
|
||||
},
|
||||
splitSelectedKey () {
|
||||
const selectedKeys = this.selectedKeys;
|
||||
if (selectedKeys.length > 0) {
|
||||
this.leftCheckedKeys = this.leftData
|
||||
.filter(data => selectedKeys.indexOf(data.key) > -1)
|
||||
.map(data => data.key);
|
||||
this.rightCheckedKeys = this.rightData
|
||||
.filter(data => selectedKeys.indexOf(data.key) > -1)
|
||||
.map(data => data.key);
|
||||
}
|
||||
},
|
||||
moveTo (direction) {
|
||||
const targetKeys = this.targetKeys;
|
||||
const opposite = direction === 'left' ? 'right' : 'left';
|
||||
const moveKeys = this.getValidKeys(opposite);
|
||||
const newTargetKeys = direction === 'right' ?
|
||||
moveKeys.concat(targetKeys) :
|
||||
targetKeys.filter(targetKey => !moveKeys.some(checkedKey => targetKey === checkedKey));
|
||||
|
||||
this.$refs[opposite].toggleSelectAll(false);
|
||||
this.$emit('on-change', newTargetKeys, direction, moveKeys);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
targetKeys () {
|
||||
this.splitData(false);
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.splitData(true);
|
||||
}
|
||||
}
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue