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,7 +3,11 @@ | ||
| 3 | <br><br><br><br><br> | 3 | <br><br><br><br><br> |
| 4 | <Table border :columns="columns1" height="500" :data="data1"></Table> | 4 | <Table border :columns="columns1" height="500" :data="data1"></Table> |
| 5 | <br><br><br><br><br> | 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 | <br><br><br><br><br> | 11 | <br><br><br><br><br> |
| 8 | </div> | 12 | </div> |
| 9 | </template> | 13 | </template> |
| @@ -17,7 +21,25 @@ | @@ -17,7 +21,25 @@ | ||
| 17 | key: 'name', | 21 | key: 'name', |
| 18 | align: 'center', | 22 | align: 'center', |
| 19 | width: 200, | 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 | title: 'Other', | 45 | title: 'Other', |
| @@ -27,7 +49,8 @@ | @@ -27,7 +49,8 @@ | ||
| 27 | title: 'Age', | 49 | title: 'Age', |
| 28 | key: 'age', | 50 | key: 'age', |
| 29 | align: 'center', | 51 | align: 'center', |
| 30 | - width: 200 | 52 | + width: 200, |
| 53 | + sortable: true | ||
| 31 | }, | 54 | }, |
| 32 | { | 55 | { |
| 33 | title: 'Address', | 56 | title: 'Address', |
| @@ -47,7 +70,8 @@ | @@ -47,7 +70,8 @@ | ||
| 47 | title: 'Building', | 70 | title: 'Building', |
| 48 | key: 'building', | 71 | key: 'building', |
| 49 | align: 'center', | 72 | align: 'center', |
| 50 | - width: 200 | 73 | + width: 200, |
| 74 | + sortable: true | ||
| 51 | }, | 75 | }, |
| 52 | { | 76 | { |
| 53 | title: 'Door No.', | 77 | title: 'Door No.', |
| @@ -210,12 +234,111 @@ | @@ -210,12 +234,111 @@ | ||
| 210 | city: 'Ottawa', | 234 | city: 'Ottawa', |
| 211 | zip: 100000 | 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 | mounted () { | 339 | mounted () { |
| 217 | const data = []; | 340 | const data = []; |
| 218 | - for (let i = 0; i < 100; i++) { | 341 | + for (let i = 0; i < 20; i++) { |
| 219 | data.push({ | 342 | data.push({ |
| 220 | key: i, | 343 | key: i, |
| 221 | name: 'John Brown', | 344 | name: 'John Brown', |
src/components/table/table-head.vue
| @@ -17,42 +17,42 @@ | @@ -17,42 +17,42 @@ | ||
| 17 | </template> | 17 | </template> |
| 18 | <template v-else-if="column.type === 'selection'"><Checkbox :value="isSelectAll" :disabled="!data.length" @on-change="selectAll"></Checkbox></template> | 18 | <template v-else-if="column.type === 'selection'"><Checkbox :value="isSelectAll" :disabled="!data.length" @on-change="selectAll"></Checkbox></template> |
| 19 | <template v-else> | 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 | <render-header v-else :render="column.renderHeader" :column="column" :index="index"></render-header> | 21 | <render-header v-else :render="column.renderHeader" :column="column" :index="index"></render-header> |
| 22 | <span :class="[prefixCls + '-sort']" v-if="column.sortable"> | 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 | </span> | 25 | </span> |
| 26 | <Poptip | 26 | <Poptip |
| 27 | v-if="isPopperShow(column)" | 27 | v-if="isPopperShow(column)" |
| 28 | - v-model="column._filterVisible" | 28 | + v-model="getColumn(rowIndex, index)._filterVisible" |
| 29 | placement="bottom" | 29 | placement="bottom" |
| 30 | popper-class="ivu-table-popper" | 30 | popper-class="ivu-table-popper" |
| 31 | transfer | 31 | transfer |
| 32 | - @on-popper-hide="handleFilterHide(column._index)"> | 32 | + @on-popper-hide="handleFilterHide(getColumn(rowIndex, index)._index)"> |
| 33 | <span :class="[prefixCls + '-filter']"> | 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 | </span> | 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 | <div :class="[prefixCls + '-filter-list-item']"> | 37 | <div :class="[prefixCls + '-filter-list-item']"> |
| 38 | - <checkbox-group v-model="column._filterChecked"> | 38 | + <checkbox-group v-model="getColumn(rowIndex, index)._filterChecked"> |
| 39 | <checkbox v-for="(item, index) in column.filters" :key="index" :label="item.value">{{ item.label }}</checkbox> | 39 | <checkbox v-for="(item, index) in column.filters" :key="index" :label="item.value">{{ item.label }}</checkbox> |
| 40 | </checkbox-group> | 40 | </checkbox-group> |
| 41 | </div> | 41 | </div> |
| 42 | <div :class="[prefixCls + '-filter-footer']"> | 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 | </div> | 45 | </div> |
| 46 | </div> | 46 | </div> |
| 47 | <div slot="content" :class="[prefixCls + '-filter-list']" v-else> | 47 | <div slot="content" :class="[prefixCls + '-filter-list']" v-else> |
| 48 | <ul :class="[prefixCls + '-filter-list-single']"> | 48 | <ul :class="[prefixCls + '-filter-list-single']"> |
| 49 | <li | 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 | <li | 52 | <li |
| 53 | - :class="itemClasses(column, item)" | 53 | + :class="itemClasses(getColumn(rowIndex, index), item)" |
| 54 | v-for="item in column.filters" | 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 | </ul> | 56 | </ul> |
| 57 | </div> | 57 | </div> |
| 58 | </Poptip> | 58 | </Poptip> |
| @@ -186,6 +186,11 @@ | @@ -186,6 +186,11 @@ | ||
| 186 | }, | 186 | }, |
| 187 | handleFilterHide (index) { | 187 | handleFilterHide (index) { |
| 188 | this.$parent.handleFilterHide(index); | 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 | }; |