Commit 9ea47cb3d276e779dbc4c88a70ae746b0a1c0d0f
1 parent
c1e965c3
fixed Table multiple head filter & sort bug
Showing
2 changed files
with
148 additions
and
20 deletions
Show diff stats
examples/routers/table.vue
| ... | ... | @@ -3,7 +3,11 @@ |
| 3 | 3 | <br><br><br><br><br> |
| 4 | 4 | <Table border :columns="columns1" height="500" :data="data1"></Table> |
| 5 | 5 | <br><br><br><br><br> |
| 6 | - <Table width="550" height="200" border :columns="columns2" :data="data4"></Table> | |
| 6 | + <!--<Table width="550" height="200" border :columns="columns2" :data="data4"></Table>--> | |
| 7 | + <!--<br><br><br><br><br>--> | |
| 8 | + <Table border :columns="columns5" :data="data5"></Table> | |
| 9 | + <br><br><br><br><br> | |
| 10 | + <Table border :columns="columns6" :data="data5"></Table> | |
| 7 | 11 | <br><br><br><br><br> |
| 8 | 12 | </div> |
| 9 | 13 | </template> |
| ... | ... | @@ -17,7 +21,25 @@ |
| 17 | 21 | key: 'name', |
| 18 | 22 | align: 'center', |
| 19 | 23 | width: 200, |
| 20 | - fixed: 'left' | |
| 24 | + fixed: 'left', | |
| 25 | + filters: [ | |
| 26 | + { | |
| 27 | + label: 'Joe', | |
| 28 | + value: 1 | |
| 29 | + }, | |
| 30 | + { | |
| 31 | + label: 'John', | |
| 32 | + value: 2 | |
| 33 | + } | |
| 34 | + ], | |
| 35 | + filterMultiple: false, | |
| 36 | + filterMethod (value, row) { | |
| 37 | + if (value === 1) { | |
| 38 | + return row.name === 'Joe'; | |
| 39 | + } else if (value === 2) { | |
| 40 | + return row.name === 'John Brown'; | |
| 41 | + } | |
| 42 | + } | |
| 21 | 43 | }, |
| 22 | 44 | { |
| 23 | 45 | title: 'Other', |
| ... | ... | @@ -27,7 +49,8 @@ |
| 27 | 49 | title: 'Age', |
| 28 | 50 | key: 'age', |
| 29 | 51 | align: 'center', |
| 30 | - width: 200 | |
| 52 | + width: 200, | |
| 53 | + sortable: true | |
| 31 | 54 | }, |
| 32 | 55 | { |
| 33 | 56 | title: 'Address', |
| ... | ... | @@ -47,7 +70,8 @@ |
| 47 | 70 | title: 'Building', |
| 48 | 71 | key: 'building', |
| 49 | 72 | align: 'center', |
| 50 | - width: 200 | |
| 73 | + width: 200, | |
| 74 | + sortable: true | |
| 51 | 75 | }, |
| 52 | 76 | { |
| 53 | 77 | title: 'Door No.', |
| ... | ... | @@ -210,12 +234,111 @@ |
| 210 | 234 | city: 'Ottawa', |
| 211 | 235 | zip: 100000 |
| 212 | 236 | } |
| 213 | - ] | |
| 237 | + ], | |
| 238 | + columns5: [ | |
| 239 | + { | |
| 240 | + title: 'Date', | |
| 241 | + key: 'date', | |
| 242 | + sortable: true | |
| 243 | + }, | |
| 244 | + { | |
| 245 | + title: 'Name', | |
| 246 | + key: 'name' | |
| 247 | + }, | |
| 248 | + { | |
| 249 | + title: 'Age', | |
| 250 | + key: 'age', | |
| 251 | + sortable: true | |
| 252 | + }, | |
| 253 | + { | |
| 254 | + title: 'Address', | |
| 255 | + key: 'address' | |
| 256 | + } | |
| 257 | + ], | |
| 258 | + data5: [ | |
| 259 | + { | |
| 260 | + name: 'John Brown', | |
| 261 | + age: 18, | |
| 262 | + address: 'New York No. 1 Lake Park', | |
| 263 | + date: '2016-10-03' | |
| 264 | + }, | |
| 265 | + { | |
| 266 | + name: 'Jim Green', | |
| 267 | + age: 24, | |
| 268 | + address: 'London No. 1 Lake Park', | |
| 269 | + date: '2016-10-01' | |
| 270 | + }, | |
| 271 | + { | |
| 272 | + name: 'Joe Black', | |
| 273 | + age: 30, | |
| 274 | + address: 'Sydney No. 1 Lake Park', | |
| 275 | + date: '2016-10-02' | |
| 276 | + }, | |
| 277 | + { | |
| 278 | + name: 'Jon Snow', | |
| 279 | + age: 26, | |
| 280 | + address: 'Ottawa No. 2 Lake Park', | |
| 281 | + date: '2016-10-04' | |
| 282 | + } | |
| 283 | + ], | |
| 284 | + columns6: [ | |
| 285 | + { | |
| 286 | + title: 'Date', | |
| 287 | + key: 'date' | |
| 288 | + }, | |
| 289 | + { | |
| 290 | + title: 'Name', | |
| 291 | + key: 'name' | |
| 292 | + }, | |
| 293 | + { | |
| 294 | + title: 'Age', | |
| 295 | + key: 'age', | |
| 296 | + filters: [ | |
| 297 | + { | |
| 298 | + label: 'Greater than 25', | |
| 299 | + value: 1 | |
| 300 | + }, | |
| 301 | + { | |
| 302 | + label: 'Less than 25', | |
| 303 | + value: 2 | |
| 304 | + } | |
| 305 | + ], | |
| 306 | + filterMultiple: false, | |
| 307 | + filterMethod (value, row) { | |
| 308 | + if (value === 1) { | |
| 309 | + return row.age > 25; | |
| 310 | + } else if (value === 2) { | |
| 311 | + return row.age < 25; | |
| 312 | + } | |
| 313 | + } | |
| 314 | + }, | |
| 315 | + { | |
| 316 | + title: 'Address', | |
| 317 | + key: 'address', | |
| 318 | + filters: [ | |
| 319 | + { | |
| 320 | + label: 'New York', | |
| 321 | + value: 'New York' | |
| 322 | + }, | |
| 323 | + { | |
| 324 | + label: 'London', | |
| 325 | + value: 'London' | |
| 326 | + }, | |
| 327 | + { | |
| 328 | + label: 'Sydney', | |
| 329 | + value: 'Sydney' | |
| 330 | + } | |
| 331 | + ], | |
| 332 | + filterMethod (value, row) { | |
| 333 | + return row.address.indexOf(value) > -1; | |
| 334 | + } | |
| 335 | + } | |
| 336 | + ], | |
| 214 | 337 | } |
| 215 | 338 | }, |
| 216 | 339 | mounted () { |
| 217 | 340 | const data = []; |
| 218 | - for (let i = 0; i < 100; i++) { | |
| 341 | + for (let i = 0; i < 20; i++) { | |
| 219 | 342 | data.push({ |
| 220 | 343 | key: i, |
| 221 | 344 | name: 'John Brown', | ... | ... |
src/components/table/table-head.vue
| ... | ... | @@ -17,42 +17,42 @@ |
| 17 | 17 | </template> |
| 18 | 18 | <template v-else-if="column.type === 'selection'"><Checkbox :value="isSelectAll" :disabled="!data.length" @on-change="selectAll"></Checkbox></template> |
| 19 | 19 | <template v-else> |
| 20 | - <span v-if="!column.renderHeader" @click="handleSortByHead(index)">{{ column.title || '#' }}</span> | |
| 20 | + <span v-if="!column.renderHeader" @click="handleSortByHead(getColumn(rowIndex, index)._index)">{{ column.title || '#' }}</span> | |
| 21 | 21 | <render-header v-else :render="column.renderHeader" :column="column" :index="index"></render-header> |
| 22 | 22 | <span :class="[prefixCls + '-sort']" v-if="column.sortable"> |
| 23 | - <i class="ivu-icon ivu-icon-arrow-up-b" :class="{on: column._sortType === 'asc'}" @click="handleSort(index, 'asc')"></i> | |
| 24 | - <i class="ivu-icon ivu-icon-arrow-down-b" :class="{on: column._sortType === 'desc'}" @click="handleSort(index, 'desc')"></i> | |
| 23 | + <i class="ivu-icon ivu-icon-arrow-up-b" :class="{on: getColumn(rowIndex, index)._sortType === 'asc'}" @click="handleSort(getColumn(rowIndex, index)._index, 'asc')"></i> | |
| 24 | + <i class="ivu-icon ivu-icon-arrow-down-b" :class="{on: getColumn(rowIndex, index)._sortType === 'desc'}" @click="handleSort(getColumn(rowIndex, index)._index, 'desc')"></i> | |
| 25 | 25 | </span> |
| 26 | 26 | <Poptip |
| 27 | 27 | v-if="isPopperShow(column)" |
| 28 | - v-model="column._filterVisible" | |
| 28 | + v-model="getColumn(rowIndex, index)._filterVisible" | |
| 29 | 29 | placement="bottom" |
| 30 | 30 | popper-class="ivu-table-popper" |
| 31 | 31 | transfer |
| 32 | - @on-popper-hide="handleFilterHide(column._index)"> | |
| 32 | + @on-popper-hide="handleFilterHide(getColumn(rowIndex, index)._index)"> | |
| 33 | 33 | <span :class="[prefixCls + '-filter']"> |
| 34 | - <i class="ivu-icon ivu-icon-funnel" :class="{on: column._isFiltered}"></i> | |
| 34 | + <i class="ivu-icon ivu-icon-funnel" :class="{on: getColumn(rowIndex, index)._isFiltered}"></i> | |
| 35 | 35 | </span> |
| 36 | - <div slot="content" :class="[prefixCls + '-filter-list']" v-if="column._filterMultiple"> | |
| 36 | + <div slot="content" :class="[prefixCls + '-filter-list']" v-if="getColumn(rowIndex, index)._filterMultiple"> | |
| 37 | 37 | <div :class="[prefixCls + '-filter-list-item']"> |
| 38 | - <checkbox-group v-model="column._filterChecked"> | |
| 38 | + <checkbox-group v-model="getColumn(rowIndex, index)._filterChecked"> | |
| 39 | 39 | <checkbox v-for="(item, index) in column.filters" :key="index" :label="item.value">{{ item.label }}</checkbox> |
| 40 | 40 | </checkbox-group> |
| 41 | 41 | </div> |
| 42 | 42 | <div :class="[prefixCls + '-filter-footer']"> |
| 43 | - <i-button type="text" size="small" :disabled="!column._filterChecked.length" @click.native="handleFilter(column._index)">{{ t('i.table.confirmFilter') }}</i-button> | |
| 44 | - <i-button type="text" size="small" @click.native="handleReset(column._index)">{{ t('i.table.resetFilter') }}</i-button> | |
| 43 | + <i-button type="text" size="small" :disabled="!getColumn(rowIndex, index)._filterChecked.length" @click.native="handleFilter(getColumn(rowIndex, index)._index)">{{ t('i.table.confirmFilter') }}</i-button> | |
| 44 | + <i-button type="text" size="small" @click.native="handleReset(getColumn(rowIndex, index)._index)">{{ t('i.table.resetFilter') }}</i-button> | |
| 45 | 45 | </div> |
| 46 | 46 | </div> |
| 47 | 47 | <div slot="content" :class="[prefixCls + '-filter-list']" v-else> |
| 48 | 48 | <ul :class="[prefixCls + '-filter-list-single']"> |
| 49 | 49 | <li |
| 50 | - :class="itemAllClasses(column)" | |
| 51 | - @click="handleReset(column._index)">{{ t('i.table.clearFilter') }}</li> | |
| 50 | + :class="itemAllClasses(getColumn(rowIndex, index))" | |
| 51 | + @click="handleReset(getColumn(rowIndex, index)._index)">{{ t('i.table.clearFilter') }}</li> | |
| 52 | 52 | <li |
| 53 | - :class="itemClasses(column, item)" | |
| 53 | + :class="itemClasses(getColumn(rowIndex, index), item)" | |
| 54 | 54 | v-for="item in column.filters" |
| 55 | - @click="handleSelect(column._index, item.value)">{{ item.label }}</li> | |
| 55 | + @click="handleSelect(getColumn(rowIndex, index)._index, item.value)">{{ item.label }}</li> | |
| 56 | 56 | </ul> |
| 57 | 57 | </div> |
| 58 | 58 | </Poptip> |
| ... | ... | @@ -186,6 +186,11 @@ |
| 186 | 186 | }, |
| 187 | 187 | handleFilterHide (index) { |
| 188 | 188 | this.$parent.handleFilterHide(index); |
| 189 | + }, | |
| 190 | + // 因为表头嵌套不是深拷贝,所以没有 _ 开头的方法,在 isGroup 下用此列 | |
| 191 | + getColumn (rowIndex, index) { | |
| 192 | + const isGroup = this.columnRows.length > 1; | |
| 193 | + return isGroup ? this.columns[rowIndex] : this.headRows[rowIndex][index]; | |
| 189 | 194 | } |
| 190 | 195 | } |
| 191 | 196 | }; | ... | ... |