diff --git a/examples/docs/en-US/transfer.md b/examples/docs/en-US/transfer.md index 19397f41c..bbc1aafd7 100644 --- a/examples/docs/en-US/transfer.md +++ b/examples/docs/en-US/transfer.md @@ -264,6 +264,7 @@ By default, Transfer looks for `key`, `label` and `disabled` in a data item. If | filterable | whether Transfer is filterable | boolean | — | false | | filter-placeholder | placeholder for the filter input | string | — | Enter keyword | | filter-method | custom filter method | function | — | — | +| target-order | order strategy for elements in the target list. If set to `original`, the elements will keep the same order as the data source. If set to `push`, the newly added elements will be pushed to the bottom. If set to `unshift`, the newly added elements will be inserted on the top | string | original / push / unshift | original | | titles | custom list titles | array | — | ['List 1', 'List 2'] | | button-texts | custom button texts | array | — | [ ] | | render-content | custom render function for data items | function(h, option) | — | — | diff --git a/examples/docs/es/transfer.md b/examples/docs/es/transfer.md index 6a988705b..7ecfa0a3b 100644 --- a/examples/docs/es/transfer.md +++ b/examples/docs/es/transfer.md @@ -265,6 +265,7 @@ Por defecto Transfer busca los atributos `key`, `label`, y `disabled` en cada el | filterable | Si se puede filtrar | boolean | — | false | | filter-placeholder | Placeholder para el input del filtro | string | — | Enter keyword | | filter-method | Método de filtrado | function | — | — | +| target-order | order strategy for elements in the target list. If set to `original`, the elements will keep the same order as the data source. If set to `push`, the newly added elements will be pushed to the bottom. If set to `unshift`, the newly added elements will be inserted on the top | string | original / push / unshift | original | | titles | Títulos de las listas | array | — | ['List 1', 'List 2'] | | button-texts | Texto de los botones | array | — | [ ] | | render-content | Función de renderizado | function(h, option) | — | — | diff --git a/examples/docs/zh-CN/transfer.md b/examples/docs/zh-CN/transfer.md index 9314974c2..da5c32b40 100644 --- a/examples/docs/zh-CN/transfer.md +++ b/examples/docs/zh-CN/transfer.md @@ -261,6 +261,7 @@ | filterable | 是否可搜索 | boolean | — | false | | filter-placeholder | 搜索框占位符 | string | — | 请输入搜索内容 | | filter-method | 自定义搜索方法 | function | — | — | +| target-order | 右侧列表元素的排序策略:若为 `original`,则保持与数据源相同的顺序;若为 `push`,则新加入的元素排在最后;若为 `unshift`,则新加入的元素排在最前 | string | original / push / unshift | original | | titles | 自定义列表标题 | array | — | ['列表 1', '列表 2'] | | button-texts | 自定义按钮文案 | array | — | [ ] | | render-content | 自定义数据项渲染函数 | function(h, option) | — | — | diff --git a/packages/transfer/src/main.vue b/packages/transfer/src/main.vue index 5e9d28f10..a1a4a3142 100644 --- a/packages/transfer/src/main.vue +++ b/packages/transfer/src/main.vue @@ -117,6 +117,10 @@ disabled: 'disabled' }; } + }, + targetOrder: { + type: String, + default: 'original' } }, @@ -128,12 +132,19 @@ }, computed: { + dataObj() { + const key = this.props.key; + return this.data.reduce((o, cur) => (o[cur[key]] = cur) && o, {}); + }, + sourceData() { return this.data.filter(item => this.value.indexOf(item[this.props.key]) === -1); }, targetData() { - return this.data.filter(item => this.value.indexOf(item[this.props.key]) > -1); + return this.targetOrder === 'original' + ? this.data.filter(item => this.value.indexOf(item[this.props.key]) > -1) + : this.value.map(key => this.dataObj[key]); }, hasButtonTexts() { @@ -178,11 +189,20 @@ addToRight() { let currentValue = this.value.slice(); - this.leftChecked.forEach(item => { - if (this.value.indexOf(item) === -1) { - currentValue = currentValue.concat(item); + const itemsToBeMoved = []; + const key = this.props.key; + this.data.forEach(item => { + const itemKey = item[key]; + if ( + this.leftChecked.indexOf(itemKey) > -1 && + this.value.indexOf(itemKey) === -1 + ) { + itemsToBeMoved.push(itemKey); } }); + currentValue = this.targetOrder === 'unshift' + ? itemsToBeMoved.concat(currentValue) + : currentValue.concat(itemsToBeMoved); this.$emit('input', currentValue); this.$emit('change', currentValue, 'right', this.leftChecked); }, diff --git a/test/unit/specs/transfer.spec.js b/test/unit/specs/transfer.spec.js index b95aca6ec..79ce72914 100644 --- a/test/unit/specs/transfer.spec.js +++ b/test/unit/specs/transfer.spec.js @@ -122,4 +122,63 @@ describe('Transfer', () => { leftList.handleAllCheckedChange({ target: { checked: true } }); expect(leftList.checked.length).to.equal(12); }); + + describe('target order', () => { + it('original(default)', done => { + vm = createTransfer('v-model="value" :left-default-checked="[2, 3]"', { + data() { + return { + value: [1, 4] + }; + } + }); + const transfer = vm.$refs.transfer; + setTimeout(() => { + transfer.addToRight(); + setTimeout(() => { + const targetItems = [].slice.call(vm.$el.querySelectorAll('.el-transfer__buttons + .el-transfer-panel .el-transfer-panel__body .el-checkbox__label span')); + expect(targetItems.map(item => item.innerText)).to.deep.equal(['备选项 1', '备选项 2', '备选项 3', '备选项 4']); + done(); + }, 50); + }, 50); + }); + + it('push', done => { + vm = createTransfer('v-model="value" :left-default-checked="[2, 3]" target-order="push"', { + data() { + return { + value: [1, 4] + }; + } + }); + const transfer = vm.$refs.transfer; + setTimeout(() => { + transfer.addToRight(); + setTimeout(() => { + const targetItems = [].slice.call(vm.$el.querySelectorAll('.el-transfer__buttons + .el-transfer-panel .el-transfer-panel__body .el-checkbox__label span')); + expect(targetItems.map(item => item.innerText)).to.deep.equal(['备选项 1', '备选项 4', '备选项 2', '备选项 3']); + done(); + }, 50); + }, 50); + }); + + it('unshift', done => { + vm = createTransfer('v-model="value" :left-default-checked="[2, 3]" target-order="unshift"', { + data() { + return { + value: [1, 4] + }; + } + }); + const transfer = vm.$refs.transfer; + setTimeout(() => { + transfer.addToRight(); + setTimeout(() => { + const targetItems = [].slice.call(vm.$el.querySelectorAll('.el-transfer__buttons + .el-transfer-panel .el-transfer-panel__body .el-checkbox__label span')); + expect(targetItems.map(item => item.innerText)).to.deep.equal(['备选项 2', '备选项 3', '备选项 1', '备选项 4']); + done(); + }, 50); + }, 50); + }); + }); }); diff --git a/types/transfer.d.ts b/types/transfer.d.ts index 332e9c0bf..ac9a8cfcf 100644 --- a/types/transfer.d.ts +++ b/types/transfer.d.ts @@ -42,6 +42,9 @@ export declare class ElTransfer extends ElementUIComponent { /** Custom filter method */ filterMethod: (query: string, item: TransferData) => boolean + /** Order strategy for elements in the target list */ + targetOrder: string + /** Custom list titles */ titles: string[]