index.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <template>
  2. <div class="el-transfer">
  3. <transfer-panel v-bind="$props" ref="leftPanel" :data="sourceData" :title="titles[0] || t('el.transfer.titles.0')"
  4. :default-checked="leftDefaultChecked" :placeholder="filterPlaceholder || t('el.transfer.filterPlaceholder')"
  5. @checked-change="onSourceCheckedChange">
  6. <slot name="left-footer"></slot>
  7. </transfer-panel>
  8. <div class="el-transfer__buttons">
  9. <el-button type="primary" :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
  10. @click.native="addToLeft" :disabled="rightChecked.length === 0">
  11. <i class="el-icon-arrow-left"></i>
  12. <span v-if="buttonTexts[0] !== undefined">{{ buttonTexts[0] }}</span>
  13. </el-button>
  14. <el-button type="primary" :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
  15. @click.native="addToRight" :disabled="leftChecked.length === 0">
  16. <span v-if="buttonTexts[1] !== undefined">{{ buttonTexts[1] }}</span>
  17. <i class="el-icon-arrow-right"></i>
  18. </el-button>
  19. </div>
  20. <transfer-panel v-bind="$props" ref="rightPanel" :data="targetData" :title="titles[1] || t('el.transfer.titles.1')"
  21. :default-checked="rightDefaultChecked" :placeholder="filterPlaceholder || t('el.transfer.filterPlaceholder')"
  22. @checked-change="onTargetCheckedChange">
  23. <slot name="right-footer"></slot>
  24. </transfer-panel>
  25. </div>
  26. </template>
  27. <script>
  28. import ElButton from 'element-ui/packages/button';
  29. import Emitter from 'element-ui/src/mixins/emitter';
  30. import Locale from 'element-ui/src/mixins/locale';
  31. import TransferPanel from './transfer-panel.vue';
  32. import Migrating from 'element-ui/src/mixins/migrating';
  33. export default {
  34. name: 'ElTransfer',
  35. mixins: [Emitter, Locale, Migrating],
  36. components: {
  37. TransferPanel,
  38. ElButton
  39. },
  40. props: {
  41. data: {
  42. type: Array,
  43. default() {
  44. return [];
  45. }
  46. },
  47. titles: {
  48. type: Array,
  49. default() {
  50. return [];
  51. }
  52. },
  53. buttonTexts: {
  54. type: Array,
  55. default() {
  56. return [];
  57. }
  58. },
  59. filterPlaceholder: {
  60. type: String,
  61. default: ''
  62. },
  63. filterMethod: Function,
  64. leftDefaultChecked: {
  65. type: Array,
  66. default() {
  67. return [];
  68. }
  69. },
  70. rightDefaultChecked: {
  71. type: Array,
  72. default() {
  73. return [];
  74. }
  75. },
  76. renderContent: Function,
  77. value: {
  78. type: Array,
  79. default() {
  80. return [];
  81. }
  82. },
  83. format: {
  84. type: Object,
  85. default() {
  86. return {};
  87. }
  88. },
  89. filterable: Boolean,
  90. props: {
  91. type: Object,
  92. default() {
  93. return {
  94. label: 'label',
  95. key: 'key',
  96. disabled: 'disabled'
  97. };
  98. }
  99. },
  100. targetOrder: {
  101. type: String,
  102. default: 'original'
  103. }
  104. },
  105. data() {
  106. return {
  107. leftChecked: [],
  108. rightChecked: []
  109. };
  110. },
  111. computed: {
  112. dataObj() {
  113. const key = this.props.key;
  114. return this.data.reduce((o, cur) => (o[cur[key]] = cur) && o, {});
  115. },
  116. sourceData() {
  117. return this.data.filter(item => this.value.indexOf(item[this.props.key]) === -1);
  118. },
  119. targetData() {
  120. if (this.targetOrder === 'original') {
  121. return this.data.filter(item => this.value.indexOf(item[this.props.key]) > -1);
  122. } else {
  123. return this.value.reduce((arr, cur) => {
  124. const val = this.dataObj[cur];
  125. if (val) {
  126. arr.push(val);
  127. }
  128. return arr;
  129. }, []);
  130. }
  131. },
  132. hasButtonTexts() {
  133. return this.buttonTexts.length === 2;
  134. }
  135. },
  136. watch: {
  137. value(val) {
  138. this.dispatch('ElFormItem', 'el.form.change', val);
  139. }
  140. },
  141. methods: {
  142. getMigratingConfig() {
  143. return {
  144. props: {
  145. 'footer-format': 'footer-format is renamed to format.'
  146. }
  147. };
  148. },
  149. onSourceCheckedChange(val, movedKeys) {
  150. this.leftChecked = val;
  151. if (movedKeys === undefined) return;
  152. this.$emit('left-check-change', val, movedKeys);
  153. },
  154. onTargetCheckedChange(val, movedKeys) {
  155. this.rightChecked = val;
  156. if (movedKeys === undefined) return;
  157. this.$emit('right-check-change', val, movedKeys);
  158. },
  159. addToLeft() {
  160. let currentValue = this.value.slice();
  161. this.rightChecked.forEach(item => {
  162. const index = currentValue.indexOf(item);
  163. if (index > -1) {
  164. currentValue.splice(index, 1);
  165. }
  166. });
  167. this.$emit('input', currentValue);
  168. this.$emit('change', currentValue, 'left', this.rightChecked);
  169. },
  170. addToRight() {
  171. let currentValue = this.value.slice();
  172. const itemsToBeMoved = [];
  173. const key = this.props.key;
  174. this.data.forEach(item => {
  175. const itemKey = item[key];
  176. if (
  177. this.leftChecked.indexOf(itemKey) > -1 &&
  178. this.value.indexOf(itemKey) === -1
  179. ) {
  180. itemsToBeMoved.push(itemKey);
  181. }
  182. });
  183. currentValue = this.targetOrder === 'unshift'
  184. ? itemsToBeMoved.concat(currentValue)
  185. : currentValue.concat(itemsToBeMoved);
  186. this.$emit('input', currentValue);
  187. this.$emit('change', currentValue, 'right', this.leftChecked);
  188. },
  189. clearQuery(which) {
  190. if (which === 'left') {
  191. this.$refs.leftPanel.query = '';
  192. } else if (which === 'right') {
  193. this.$refs.rightPanel.query = '';
  194. }
  195. }
  196. }
  197. };
  198. </script>