123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- <template>
- <div class="el-transfer-panel">
- <p class="el-transfer-panel__header">
- <el-checkbox v-model="allChecked" @change="handleAllCheckedChange" :indeterminate="isIndeterminate">
- {{ title }}
- <span>{{ checkedSummary }}</span>
- </el-checkbox>
- </p>
- <div :class="['el-transfer-panel__body', hasFooter ? 'is-with-footer' : '']">
- <el-input class="el-transfer-panel__filter" v-model="query" size="small" :placeholder="placeholder"
- @mouseenter.native="inputHover = true" @mouseleave.native="inputHover = false" v-if="filterable">
- <i slot="prefix" :class="['el-input__icon', 'el-icon-' + inputIcon]" @click="clearQuery"></i>
- </el-input>
- <el-checkbox-group v-model="checked" v-show="!hasNoMatch && data.length > 0"
- :class="{ 'is-filterable': filterable }" class="el-transfer-panel__list">
- <el-checkbox class="el-transfer-panel__item" :label="item[keyProp]" :disabled="item[disabledProp]"
- :key="item[keyProp]" v-for="item in filteredData">
- <option-content :option="item"></option-content>
- </el-checkbox>
- </el-checkbox-group>
- <p class="el-transfer-panel__empty" v-show="hasNoMatch">{{ t('el.transfer.noMatch') }}</p>
- <p class="el-transfer-panel__empty" v-show="data.length === 0 && !hasNoMatch">{{ t('el.transfer.noData') }}</p>
- </div>
- <p class="el-transfer-panel__footer" v-if="hasFooter">
- <slot></slot>
- </p>
- </div>
- </template>
- <script>
- import ElCheckboxGroup from 'element-ui/packages/checkbox-group';
- import ElCheckbox from 'element-ui/packages/checkbox';
- import ElInput from 'element-ui/packages/input';
- import Locale from 'element-ui/src/mixins/locale';
- export default {
- mixins: [Locale],
- name: 'ElTransferPanel',
- componentName: 'ElTransferPanel',
- components: {
- ElCheckboxGroup,
- ElCheckbox,
- ElInput,
- OptionContent: {
- props: {
- option: Object
- },
- render(h) {
- const getParent = vm => {
- if (vm.$options.componentName === 'ElTransferPanel') {
- return vm;
- } else if (vm.$parent) {
- return getParent(vm.$parent);
- } else {
- return vm;
- }
- };
- const panel = getParent(this);
- const transfer = panel.$parent || panel;
- return panel.renderContent
- ? panel.renderContent(h, this.option)
- : transfer.$scopedSlots.default
- ? transfer.$scopedSlots.default({ option: this.option })
- : <span>{this.option[panel.labelProp] || this.option[panel.keyProp]}</span>;
- }
- }
- },
- props: {
- data: {
- type: Array,
- default() {
- return [];
- }
- },
- renderContent: Function,
- placeholder: String,
- title: String,
- filterable: Boolean,
- format: Object,
- filterMethod: Function,
- defaultChecked: Array,
- props: Object
- },
- data() {
- return {
- checked: [],
- allChecked: false,
- query: '',
- inputHover: false,
- checkChangeByUser: true
- };
- },
- watch: {
- checked(val, oldVal) {
- this.updateAllChecked();
- if (this.checkChangeByUser) {
- const movedKeys = val.concat(oldVal)
- .filter(v => val.indexOf(v) === -1 || oldVal.indexOf(v) === -1);
- this.$emit('checked-change', val, movedKeys);
- } else {
- this.$emit('checked-change', val);
- this.checkChangeByUser = true;
- }
- },
- data() {
- const checked = [];
- const filteredDataKeys = this.filteredData.map(item => item[this.keyProp]);
- this.checked.forEach(item => {
- if (filteredDataKeys.indexOf(item) > -1) {
- checked.push(item);
- }
- });
- this.checkChangeByUser = false;
- this.checked = checked;
- },
- checkableData() {
- this.updateAllChecked();
- },
- defaultChecked: {
- immediate: true,
- handler(val, oldVal) {
- if (oldVal && val.length === oldVal.length &&
- val.every(item => oldVal.indexOf(item) > -1)) return;
- const checked = [];
- const checkableDataKeys = this.checkableData.map(item => item[this.keyProp]);
- val.forEach(item => {
- if (checkableDataKeys.indexOf(item) > -1) {
- checked.push(item);
- }
- });
- this.checkChangeByUser = false;
- this.checked = checked;
- }
- }
- },
- computed: {
- filteredData() {
- return this.data.filter(item => {
- if (typeof this.filterMethod === 'function') {
- return this.filterMethod(this.query, item);
- } else {
- const label = item[this.labelProp] || item[this.keyProp].toString();
- return label.toLowerCase().indexOf(this.query.toLowerCase()) > -1;
- }
- });
- },
- checkableData() {
- return this.filteredData.filter(item => !item[this.disabledProp]);
- },
- checkedSummary() {
- const checkedLength = this.checked.length;
- const dataLength = this.data.length;
- const { noChecked, hasChecked } = this.format;
- if (noChecked && hasChecked) {
- return checkedLength > 0
- ? hasChecked.replace(/\${checked}/g, checkedLength).replace(/\${total}/g, dataLength)
- : noChecked.replace(/\${total}/g, dataLength);
- } else {
- return `${checkedLength}/${dataLength}`;
- }
- },
- isIndeterminate() {
- const checkedLength = this.checked.length;
- return checkedLength > 0 && checkedLength < this.checkableData.length;
- },
- hasNoMatch() {
- return this.query.length > 0 && this.filteredData.length === 0;
- },
- inputIcon() {
- return this.query.length > 0 && this.inputHover
- ? 'circle-close'
- : 'search';
- },
- labelProp() {
- return this.props.label || 'label';
- },
- keyProp() {
- return this.props.key || 'key';
- },
- disabledProp() {
- return this.props.disabled || 'disabled';
- },
- hasFooter() {
- return !!this.$slots.default;
- }
- },
- methods: {
- updateAllChecked() {
- const checkableDataKeys = this.checkableData.map(item => item[this.keyProp]);
- this.allChecked = checkableDataKeys.length > 0 &&
- checkableDataKeys.every(item => this.checked.indexOf(item) > -1);
- },
- handleAllCheckedChange(value) {
- this.checked = value
- ? this.checkableData.map(item => item[this.keyProp])
- : [];
- },
- clearQuery() {
- if (this.inputIcon === 'circle-close') {
- this.query = '';
- }
- }
- }
- };
- </script>
|