support Transfer

support Transfer
This commit is contained in:
梁灏 2017-03-07 15:06:38 +08:00
parent 191068ac0c
commit 5b19b5f55f
8 changed files with 198 additions and 55 deletions

View file

@ -46,6 +46,7 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; }
<li><router-link to="/select">Select</router-link></li> <li><router-link to="/select">Select</router-link></li>
<li><router-link to="/backtop">Backtop</router-link></li> <li><router-link to="/backtop">Backtop</router-link></li>
<li><router-link to="/page">Page</router-link></li> <li><router-link to="/page">Page</router-link></li>
<li><router-link to="/transfer">Transfer</router-link></li>
</ul> </ul>
</nav> </nav>
<router-view></router-view> <router-view></router-view>

View file

@ -148,6 +148,10 @@ const router = new VueRouter({
{ {
path: '/page', path: '/page',
component: require('./routers/page.vue') component: require('./routers/page.vue')
},
{
path: '/transfer',
component: require('./routers/transfer.vue')
} }
] ]
}); });

View file

@ -1,18 +1,77 @@
<!--<template>-->
<!--<div>-->
<!--<Transfer-->
<!--:data="data1"-->
<!--filterable-->
<!--:target-keys="targetKeys1"-->
<!--:render-format="render1"-->
<!--@on-change="handleChange1"></Transfer>-->
<!--</div>-->
<!--</template>-->
<!--<script>-->
<!--export default {-->
<!--data () {-->
<!--return {-->
<!--data1: this.getMockData(),-->
<!--targetKeys1: this.getTargetKeys()-->
<!--}-->
<!--},-->
<!--methods: {-->
<!--getMockData () {-->
<!--let mockData = [];-->
<!--for (let i = 1; i <= 20; i++) {-->
<!--mockData.push({-->
<!--key: i.toString(),-->
<!--label: '内容' + i,-->
<!--description: '内容' + i + '的描述信息',-->
<!--disabled: Math.random() * 3 < 1-->
<!--});-->
<!--}-->
<!--return mockData;-->
<!--},-->
<!--getTargetKeys () {-->
<!--return this.getMockData()-->
<!--.filter(() => Math.random() * 2 > 1)-->
<!--.map(item => item.key);-->
<!--},-->
<!--render1 (item) {-->
<!--return item.label;-->
<!--},-->
<!--handleChange1 (newTargetKeys, direction, moveKeys) {-->
<!--console.log(newTargetKeys);-->
<!--console.log(direction);-->
<!--console.log(moveKeys);-->
<!--this.targetKeys1 = newTargetKeys;-->
<!--}-->
<!--}-->
<!--}-->
<!--</script>-->
<template> <template>
<Transfer <Transfer
:data="data2" :data="data3"
:target-keys="targetKeys2" :target-keys="targetKeys3"
:list-style="listStyle"
:render-format="render3"
:operations="['向左移动','向右移动']"
filterable filterable
:render-format="rf" @on-change="handleChange3">
:filter-method="filterMethod" <div :style="{float: 'right', margin: '5px'}">
@on-change="handleChange2"></Transfer> <Button type="ghost" size="small" @click.native="reloadMockData">刷新</Button>
</div>
</Transfer>
</template> </template>
<script> <script>
export default { export default {
data () { data () {
return { return {
data2: this.getMockData(), data3: this.getMockData(),
targetKeys2: this.getTargetKeys() targetKeys3: this.getTargetKeys(),
listStyle: {
width: '250px',
height: '300px'
}
} }
}, },
methods: { methods: {
@ -33,15 +92,59 @@
.filter(() => Math.random() * 2 > 1) .filter(() => Math.random() * 2 > 1)
.map(item => item.key); .map(item => item.key);
}, },
handleChange2 (newTargetKeys) { handleChange3 (newTargetKeys) {
this.targetKeys2 = newTargetKeys; this.targetKeys3 = newTargetKeys;
}, },
filterMethod (data, query) { render3 (item) {
return data.label.indexOf(query) > -1; return item.label + ' - ' + item.description;
}, },
rf (data) { reloadMockData () {
return '<i class="ivu-icon ivu-icon-alert"></i>' + data.label; this.data3 = this.getMockData();
this.targetKeys3 = this.getTargetKeys();
} }
} }
} }
</script> </script>
<!--<template>-->
<!--<Transfer-->
<!--:data="data4"-->
<!--:target-keys="targetKeys4"-->
<!--:render-format="render4"-->
<!--@on-change="handleChange4"></Transfer>-->
<!--</template>-->
<!--<script>-->
<!--export default {-->
<!--data () {-->
<!--return {-->
<!--data4: this.getMockData(),-->
<!--targetKeys4: this.getTargetKeys()-->
<!--}-->
<!--},-->
<!--methods: {-->
<!--getMockData () {-->
<!--let mockData = [];-->
<!--for (let i = 1; i <= 20; i++) {-->
<!--mockData.push({-->
<!--key: i.toString(),-->
<!--label: '内容' + i,-->
<!--description: '内容' + i + '的描述信息',-->
<!--disabled: Math.random() * 3 < 1-->
<!--});-->
<!--}-->
<!--return mockData;-->
<!--},-->
<!--getTargetKeys () {-->
<!--return this.getMockData()-->
<!--.filter(() => Math.random() * 2 > 1)-->
<!--.map(item => item.key);-->
<!--},-->
<!--handleChange4 (newTargetKeys) {-->
<!--this.targetKeys4 = newTargetKeys;-->
<!--},-->
<!--render4 (item) {-->
<!--return item.label + ' - ' + item.description;-->
<!--}-->
<!--}-->
<!--}-->
<!--</script>-->

View file

@ -1,7 +1,7 @@
<template> <template>
<div :class="classes" :style="style"> <div :class="classes" :style="style">
<div :class="prefixCls + '-header'"> <div :class="prefixCls + '-header'">
<Checkbox :checked.sync="checkedAll" :disabled="checkedAllDisabled" @on-change="toggleSelectAll"></Checkbox> <Checkbox :value="checkedAll" :disabled="checkedAllDisabled" @on-change="toggleSelectAll"></Checkbox>
<span>{{ title }}</span> <span>{{ title }}</span>
<span :class="prefixCls + '-header-count'">{{ count }}</span> <span :class="prefixCls + '-header-count'">{{ count }}</span>
</div> </div>
@ -9,21 +9,23 @@
<div :class="prefixCls + '-body-search-wrapper'" v-if="filterable"> <div :class="prefixCls + '-body-search-wrapper'" v-if="filterable">
<Search <Search
:prefix-cls="prefixCls + '-search'" :prefix-cls="prefixCls + '-search'"
:query.sync="query" :query="query"
@on-query-clear="handleQueryClear"
@on-query-change="handleQueryChange"
:placeholder="filterPlaceholder"></Search> :placeholder="filterPlaceholder"></Search>
</div> </div>
<ul :class="prefixCls + '-content'"> <ul :class="prefixCls + '-content'">
<li <li
v-for="item in showItems | filterBy filterData" v-for="item in filterData"
:class="itemClasses(item)" :class="itemClasses(item)"
@click.prevent="select(item)"> @click.prevent="select(item)">
<Checkbox :checked="isCheck(item)" :disabled="item.disabled"></Checkbox> <Checkbox :value="isCheck(item)" :disabled="item.disabled"></Checkbox>
<span>{{{ showLabel(item) }}}</span> <span v-html="showLabel(item)"></span>
</li> </li>
<li :class="prefixCls + '-content-not-found'">{{ notFoundText }}</li> <li :class="prefixCls + '-content-not-found'">{{ notFoundText }}</li>
</ul> </ul>
</div> </div>
<div :class="prefixCls + '-footer'" v-if="showFooter" v-el:footer><slot></slot></div> <div :class="prefixCls + '-footer'" v-if="showFooter"><slot></slot></div>
</div> </div>
</template> </template>
<script> <script>
@ -31,6 +33,7 @@
import Checkbox from '../checkbox/checkbox.vue'; import Checkbox from '../checkbox/checkbox.vue';
export default { export default {
name: 'TransferList',
components: { Search, Checkbox }, components: { Search, Checkbox },
props: { props: {
prefixCls: String, prefixCls: String,
@ -52,6 +55,11 @@
showFooter: true showFooter: true
}; };
}, },
watch: {
data () {
this.updateFilteredData();
}
},
computed: { computed: {
classes () { classes () {
return [ return [
@ -79,6 +87,9 @@
}, },
checkedAllDisabled () { checkedAllDisabled () {
return this.data.filter(data => !data.disabled).length <= 0; return this.data.filter(data => !data.disabled).length <= 0;
},
filterData () {
return this.showItems.filter(item => this.filterMethod(item, this.query));
} }
}, },
methods: { methods: {
@ -105,25 +116,23 @@
this.showItems = this.data; this.showItems = this.data;
}, },
toggleSelectAll (status) { toggleSelectAll (status) {
this.checkedKeys = 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.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);
}, },
filterData (value) { handleQueryClear () {
return this.filterMethod(value, this.query); this.query = '';
},
handleQueryChange (val) {
this.query = val;
} }
}, },
created () { created () {
this.updateFilteredData(); this.updateFilteredData();
}, },
compiled () { mounted () {
this.showFooter = this.$els.footer.innerHTML !== ''; this.showFooter = this.$slots.default !== undefined;
},
watch: {
data () {
this.updateFilteredData();
}
} }
}; };
</script> </script>

View file

@ -1,9 +1,9 @@
<template> <template>
<div :class="prefixCls + '-operation'"> <div :class="prefixCls + '-operation'">
<i-button type="primary" size="small" :disabled="!rightActive" @click="moveToLeft"> <i-button type="primary" size="small" :disabled="!rightActive" @click.native="moveToLeft">
<Icon type="ios-arrow-left"></Icon> {{ operations[0] }} <Icon type="ios-arrow-left"></Icon> {{ operations[0] }}
</i-button> </i-button>
<i-button type="primary" size="small" :disabled="!leftActive" @click="moveToRight"> <i-button type="primary" size="small" :disabled="!leftActive" @click.native="moveToRight">
{{ operations[1] }} <Icon type="ios-arrow-right"></Icon> {{ operations[1] }} <Icon type="ios-arrow-right"></Icon>
</i-button> </i-button>
</div> </div>
@ -13,6 +13,7 @@
import Icon from '../icon/icon.vue'; import Icon from '../icon/icon.vue';
export default { export default {
name: 'Operation',
components: { iButton, Icon }, components: { iButton, Icon },
props: { props: {
prefixCls: String, prefixCls: String,

View file

@ -1,7 +1,7 @@
<template> <template>
<div :class="prefixCls"> <div :class="prefixCls">
<i-input <i-input
:value.sync="query" v-model="currentQuery"
size="small" size="small"
:icon="icon" :icon="icon"
:placeholder="placeholder" :placeholder="placeholder"
@ -12,12 +12,26 @@
import iInput from '../input/input.vue'; import iInput from '../input/input.vue';
export default { export default {
name: 'Search',
components: { iInput }, components: { iInput },
props: { props: {
prefixCls: String, prefixCls: String,
placeholder: String, placeholder: String,
query: String query: String
}, },
data () {
return {
currentQuery: this.query
};
},
watch: {
query (val) {
this.currentQuery = val;
},
currentQuery (val) {
this.$emit('on-query-change', val);
}
},
computed: { computed: {
icon () { icon () {
return this.query === '' ? 'ios-search' : 'ios-close'; return this.query === '' ? 'ios-search' : 'ios-close';
@ -25,17 +39,19 @@
}, },
methods: { methods: {
handleClick () { handleClick () {
if (this.query === '') return; if (this.currentQuery === '') return;
this.query = ''; this.currentQuery = '';
} this.$emit('on-query-clear');
},
events: {
'on-form-blur' () {
return false;
},
'on-form-change' () {
return false;
} }
} }
// todo
// events: {
// 'on-form-blur' () {
// return false;
// },
// 'on-form-change' () {
// return false;
// }
// }
}; };
</script> </script>

View file

@ -1,12 +1,13 @@
<template> <template>
<div :class="classes"> <div :class="classes">
<List <List
v-ref:left ref="left"
:prefix-cls="prefixCls + '-list'" :prefix-cls="prefixCls + '-list'"
:data="leftData" :data="leftData"
:render-format="renderFormat" :render-format="renderFormat"
:checked-keys.sync="leftCheckedKeys" :checked-keys="leftCheckedKeys"
:valid-keys-count.sync="leftValidKeysCount" @on-checked-keys-change="handleLeftCheckedKeysChange"
:valid-keys-count="leftValidKeysCount"
:style="listStyle" :style="listStyle"
:title="titles[0]" :title="titles[0]"
:filterable="filterable" :filterable="filterable"
@ -19,19 +20,20 @@
:operations="operations" :operations="operations"
:left-active="leftValidKeysCount > 0" :left-active="leftValidKeysCount > 0"
:right-active="rightValidKeysCount > 0"></Operation><List :right-active="rightValidKeysCount > 0"></Operation><List
v-ref:right ref="right"
:prefix-cls="prefixCls + '-list'" :prefix-cls="prefixCls + '-list'"
:data="rightData" :data="rightData"
:render-format="renderFormat" :render-format="renderFormat"
:checked-keys.sync="rightCheckedKeys" :checked-keys="rightCheckedKeys"
:valid-keys-count.sync="rightValidKeysCount" @on-checked-keys-change="handleRightCheckedKeysChange"
:valid-keys-count="rightValidKeysCount"
:style="listStyle" :style="listStyle"
:title="titles[1]" :title="titles[1]"
:filterable="filterable" :filterable="filterable"
:filter-placeholder="filterPlaceholder" :filter-placeholder="filterPlaceholder"
:filter-method="filterMethod" :filter-method="filterMethod"
:not-found-text="notFoundText"> :not-found-text="notFoundText">
<slot></slot> <slot name="right"></slot>
</List> </List>
</div> </div>
</template> </template>
@ -177,7 +179,14 @@
this.$refs[opposite].toggleSelectAll(false); this.$refs[opposite].toggleSelectAll(false);
this.$emit('on-change', newTargetKeys, direction, moveKeys); this.$emit('on-change', newTargetKeys, direction, moveKeys);
this.$dispatch('on-form-change', newTargetKeys, direction, moveKeys); // todo
// this.$dispatch('on-form-change', newTargetKeys, direction, moveKeys);
},
handleLeftCheckedKeysChange (keys) {
this.leftCheckedKeys = keys;
},
handleRightCheckedKeysChange (keys) {
this.rightCheckedKeys = keys;
} }
}, },
watch: { watch: {

View file

@ -39,7 +39,7 @@ import Tag from './components/tag';
import Timeline from './components/timeline'; import Timeline from './components/timeline';
// import TimePicker from './components/time-picker'; // import TimePicker from './components/time-picker';
import Tooltip from './components/tooltip'; import Tooltip from './components/tooltip';
// import Transfer from './components/transfer'; import Transfer from './components/transfer';
import Tree from './components/tree'; import Tree from './components/tree';
import Upload from './components/upload'; import Upload from './components/upload';
import { Row, Col } from './components/grid'; import { Row, Col } from './components/grid';
@ -107,7 +107,7 @@ const iview = {
TimelineItem: Timeline.Item, TimelineItem: Timeline.Item,
// TimePicker, // TimePicker,
Tooltip, Tooltip,
// Transfer, Transfer,
Tree, Tree,
Upload Upload
}; };