138 lines
5 KiB
Vue
138 lines
5 KiB
Vue
<template>
|
|
<div :class="classes" :style="listStyle">
|
|
<div :class="prefixCls + '-header'">
|
|
<Checkbox :value="checkedAll" :disabled="checkedAllDisabled" @on-change="toggleSelectAll"></Checkbox>
|
|
<span :class="prefixCls + '-header-title'" @click="toggleSelectAll(!checkedAll)">{{ title }}</span>
|
|
<span :class="prefixCls + '-header-count'">{{ count }}</span>
|
|
</div>
|
|
<div :class="bodyClasses">
|
|
<div :class="prefixCls + '-body-search-wrapper'" v-if="filterable">
|
|
<Search
|
|
:prefix-cls="prefixCls + '-search'"
|
|
:query="query"
|
|
@on-query-clear="handleQueryClear"
|
|
@on-query-change="handleQueryChange"
|
|
:placeholder="filterPlaceholder"></Search>
|
|
</div>
|
|
<ul :class="prefixCls + '-content'">
|
|
<li
|
|
v-for="item in filterData"
|
|
:class="itemClasses(item)"
|
|
@click.prevent="select(item)">
|
|
<Checkbox :value="isCheck(item)" :disabled="item.disabled"></Checkbox>
|
|
<span v-html="showLabel(item)"></span>
|
|
</li>
|
|
<li :class="prefixCls + '-content-not-found'">{{ notFoundText }}</li>
|
|
</ul>
|
|
</div>
|
|
<div :class="prefixCls + '-footer'" v-if="showFooter"><slot></slot></div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
import Search from './search.vue';
|
|
import Checkbox from '../checkbox/checkbox.vue';
|
|
|
|
export default {
|
|
name: 'TransferList',
|
|
components: { Search, Checkbox },
|
|
props: {
|
|
prefixCls: String,
|
|
data: Array,
|
|
renderFormat: Function,
|
|
checkedKeys: Array,
|
|
listStyle: Object,
|
|
title: [String, Number],
|
|
filterable: Boolean,
|
|
filterPlaceholder: String,
|
|
filterMethod: Function,
|
|
notFoundText: String,
|
|
validKeysCount: Number
|
|
},
|
|
data () {
|
|
return {
|
|
showItems: [],
|
|
query: '',
|
|
showFooter: true
|
|
};
|
|
},
|
|
watch: {
|
|
data () {
|
|
this.updateFilteredData();
|
|
}
|
|
},
|
|
computed: {
|
|
classes () {
|
|
return [
|
|
`${this.prefixCls}`,
|
|
{
|
|
[`${this.prefixCls}-with-footer`]: this.showFooter
|
|
}
|
|
];
|
|
},
|
|
bodyClasses () {
|
|
return [
|
|
`${this.prefixCls}-body`,
|
|
{
|
|
[`${this.prefixCls}-body-with-search`]: this.filterable,
|
|
[`${this.prefixCls}-body-with-footer`]: this.showFooter
|
|
}
|
|
];
|
|
},
|
|
count () {
|
|
const validKeysCount = this.validKeysCount;
|
|
return (validKeysCount > 0 ? `${validKeysCount}/` : '') + `${this.data.length}`;
|
|
},
|
|
checkedAll () {
|
|
return this.data.filter(data => !data.disabled).length === this.validKeysCount && this.validKeysCount !== 0;
|
|
},
|
|
checkedAllDisabled () {
|
|
return this.data.filter(data => !data.disabled).length <= 0;
|
|
},
|
|
filterData () {
|
|
return this.showItems.filter(item => this.filterMethod(item, this.query));
|
|
}
|
|
},
|
|
methods: {
|
|
itemClasses (item) {
|
|
return [
|
|
`${this.prefixCls}-content-item`,
|
|
{
|
|
[`${this.prefixCls}-content-item-disabled`]: item.disabled
|
|
}
|
|
];
|
|
},
|
|
showLabel (item) {
|
|
return this.renderFormat(item);
|
|
},
|
|
isCheck (item) {
|
|
return this.checkedKeys.some(key => key === item.key);
|
|
},
|
|
select (item) {
|
|
if (item.disabled) return;
|
|
const index = this.checkedKeys.indexOf(item.key);
|
|
index > -1 ? this.checkedKeys.splice(index, 1) : this.checkedKeys.push(item.key);
|
|
},
|
|
updateFilteredData () {
|
|
this.showItems = this.data;
|
|
},
|
|
toggleSelectAll (status) {
|
|
const keys = status ?
|
|
this.data.filter(data => !data.disabled || this.checkedKeys.indexOf(data.key) > -1).map(data => data.key) :
|
|
this.data.filter(data => data.disabled && this.checkedKeys.indexOf(data.key) > -1).map(data => data.key);
|
|
this.$emit('on-checked-keys-change', keys);
|
|
},
|
|
handleQueryClear () {
|
|
this.query = '';
|
|
},
|
|
handleQueryChange (val) {
|
|
this.query = val;
|
|
}
|
|
},
|
|
created () {
|
|
this.updateFilteredData();
|
|
},
|
|
mounted () {
|
|
this.showFooter = this.$slots.default !== undefined;
|
|
}
|
|
};
|
|
</script>
|