Browse Source

Transfer: add target-order (#9960)

杨奕 7 năm trước cách đây
mục cha
commit
aa5f015cd9

+ 1 - 0
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) | — | — |

+ 1 - 0
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)             | —                 | —                                        |

+ 1 - 0
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) | — | — |

+ 24 - 4
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);
       },

+ 59 - 0
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);
+    });
+  });
 });

+ 3 - 0
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[]