mirror of
https://github.com/Hopiu/vue-material.git
synced 2026-05-12 09:13:11 +00:00
Add sort buttons with ripple effect
This commit is contained in:
parent
c34a63b672
commit
ca83e3b16e
8 changed files with 210 additions and 37 deletions
|
|
@ -14,22 +14,23 @@
|
|||
</md-button>
|
||||
</md-toolbar>
|
||||
|
||||
<md-table md-row-selection>
|
||||
<md-table md-row-selection md-sort="calories">
|
||||
<thead>
|
||||
<md-table-row>
|
||||
<th>Head 1</th>
|
||||
<th>Head 2</th>
|
||||
<th>Head 3</th>
|
||||
<th>Head 4</th>
|
||||
<md-table-head md-sort-by="dessert">Dessert (100g serving)</md-table-head>
|
||||
<md-table-head md-sort-by="calories" md-numeric>Calories (g)</md-table-head>
|
||||
<md-table-head md-sort-by="fat" md-numeric>Fat (g)</md-table-head>
|
||||
<md-table-head md-sort-by="carbs" md-numeric>Carbs (g)</md-table-head>
|
||||
<md-table-head md-sort-by="protein" md-numeric>Protein (g)</md-table-head>
|
||||
<md-table-head md-sort-by="sodium" md-numeric>Sodium (mg)</md-table-head>
|
||||
<md-table-head md-sort-by="calcium" md-numeric>Calcium (%)</md-table-head>
|
||||
<md-table-head md-sort-by="iron" md-numeric>Iron (%)</md-table-head>
|
||||
</md-table-row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<md-table-row v-for="test in 100">
|
||||
<td>Cell 1</td>
|
||||
<td>Cell 2</td>
|
||||
<td>Cell 3</td>
|
||||
<td>Cell 4</td>
|
||||
<md-table-row v-for="(row, index) in 10" :key="index">
|
||||
<md-table-cell v-for="(col, index) in 8" :key="index" :md-numeric="index > 0">Cell</md-table-cell>
|
||||
</md-table-row>
|
||||
</tbody>
|
||||
</md-table>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
import mdTable from './mdTable.vue';
|
||||
import mdTableCard from './mdTableCard.vue';
|
||||
import mdTableHead from './mdTableHead.vue';
|
||||
import mdTableCell from './mdTableCell.vue';
|
||||
import mdTableRow from './mdTableRow.vue';
|
||||
import mdTableTheme from './mdTable.theme';
|
||||
|
||||
export default function install(Vue) {
|
||||
Vue.component('md-table', Vue.extend(mdTable));
|
||||
Vue.component('md-table-card', Vue.extend(mdTableCard));
|
||||
Vue.component('md-table-head', Vue.extend(mdTableHead));
|
||||
Vue.component('md-table-cell', Vue.extend(mdTableCell));
|
||||
Vue.component('md-table-row', Vue.extend(mdTableRow));
|
||||
|
||||
Vue.material.styles.push(mdTableTheme);
|
||||
|
|
|
|||
|
|
@ -18,34 +18,21 @@
|
|||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
tr {
|
||||
transition: $swift-ease-out;
|
||||
}
|
||||
|
||||
tbody tr {
|
||||
border-top: 1px solid #e0e0e0;
|
||||
|
||||
&:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
&.md-selected {
|
||||
&.md-selected .md-table-cell {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
padding-right: 32px;
|
||||
padding-left: 24px;
|
||||
|
||||
&:last-child {
|
||||
padding-right: 24px;
|
||||
&:hover .md-table-cell {
|
||||
background-color: #eee;
|
||||
}
|
||||
}
|
||||
|
||||
th {
|
||||
.md-table-head {
|
||||
height: 56px;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
color: rgba(#000, .54);
|
||||
|
|
@ -54,20 +41,113 @@
|
|||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
&:last-child .md-table-head-container {
|
||||
padding-right: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
.md-table-head-container {
|
||||
height: 100%;
|
||||
padding-right: 32px;
|
||||
padding-left: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: $swift-ease-out;
|
||||
}
|
||||
|
||||
.md-sortable {
|
||||
cursor: pointer;
|
||||
|
||||
&:first-of-type {
|
||||
.md-icon {
|
||||
left: auto;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&.md-sorted {
|
||||
.md-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: rgba(#000, .87);
|
||||
}
|
||||
|
||||
&.md-sorted {
|
||||
.md-icon {
|
||||
color: rgba(#000, .87);
|
||||
}
|
||||
}
|
||||
|
||||
&.md-sorted-descending {
|
||||
.md-icon {
|
||||
transform: translateY(-50%) rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
.md-icon {
|
||||
$size: 16px;
|
||||
|
||||
width: $size;
|
||||
min-width: $size;
|
||||
height: $size;
|
||||
min-height: $size;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 2px;
|
||||
transition: $swift-ease-out;
|
||||
transform: translateY(-50%);
|
||||
opacity: 0;
|
||||
color: rgba(#000, .38);
|
||||
font-size: $size;
|
||||
}
|
||||
|
||||
.md-ink-ripple {
|
||||
color: rgba(#000, .87);
|
||||
}
|
||||
}
|
||||
|
||||
.md-table-cell {
|
||||
height: 48px;
|
||||
transition: $swift-ease-out;
|
||||
color: rgba(#000, .87);
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
|
||||
&:last-child .md-table-cell-container {
|
||||
padding-right: 24px;
|
||||
}
|
||||
|
||||
.md-table-cell-container {
|
||||
padding: 0 24px 0 32px;
|
||||
}
|
||||
|
||||
&.md-numeric {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.md-table-selection {
|
||||
width: 20px;
|
||||
padding-right: 0;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
|
||||
+ {
|
||||
.md-table-cell .md-table-cell-container,
|
||||
.md-table-head .md-table-head-container {
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.md-table-cell-container {
|
||||
padding-right: 16px;
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
.md-checkbox {
|
||||
margin: 3px 0 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,14 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
mdRowSelection: Boolean
|
||||
mdRowSelection: Boolean,
|
||||
mdSortType: String,
|
||||
mdSort: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
sortType: this.mdSortType,
|
||||
sortBy: this.mdSort,
|
||||
numberOfRows: 0,
|
||||
numberOfSelected: 0,
|
||||
selectedRows: {}
|
||||
|
|
@ -28,7 +32,10 @@
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
emitSort(name) {
|
||||
this.sortBy = name;
|
||||
this.$emit('sort', name);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<md-card class="md-table-card">
|
||||
<md-card class="md-table-card" v-once>
|
||||
<slot></slot>
|
||||
</md-card>
|
||||
</template>
|
||||
|
|
|
|||
22
src/components/mdTable/mdTableCell.vue
Normal file
22
src/components/mdTable/mdTableCell.vue
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<template>
|
||||
<td class="md-table-cell" :class="classes">
|
||||
<div class="md-table-cell-container">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</td>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
mdNumeric: Boolean
|
||||
},
|
||||
computed: {
|
||||
classes() {
|
||||
return {
|
||||
'md-numeric': this.mdNumeric
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
57
src/components/mdTable/mdTableHead.vue
Normal file
57
src/components/mdTable/mdTableHead.vue
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<template>
|
||||
<th class="md-table-head" :class="classes" @click="changeSort">
|
||||
<div class="md-table-head-container" v-md-ink-ripple="!mdSortBy">
|
||||
<md-icon v-if="mdSortBy">arrow_downward</md-icon>
|
||||
|
||||
<span>
|
||||
<slot></slot>
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
mdNumeric: Boolean,
|
||||
mdSortBy: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
sortType: null,
|
||||
sorted: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
classes() {
|
||||
let matchSort = this.$parent.$parent.sortBy === this.mdSortBy;
|
||||
|
||||
if (!matchSort) {
|
||||
this.sorted = false;
|
||||
}
|
||||
|
||||
return {
|
||||
'md-sortable': this.mdSortBy,
|
||||
'md-sorted': matchSort && this.sorted,
|
||||
'md-sorted-descending': matchSort && this.sortType === 'desc'
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeSort() {
|
||||
let parent = this.$parent.$parent;
|
||||
|
||||
if (this.sortType === 'asc' && this.sorted) {
|
||||
this.sortType = 'desc';
|
||||
} else {
|
||||
this.sortType = 'asc';
|
||||
}
|
||||
|
||||
this.sorted = true;
|
||||
|
||||
parent.sortType = this.sortType;
|
||||
parent.emitSort(this.mdSortBy);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<tr class="md-table-row" :class="classes">
|
||||
<td class="md-table-selection" v-if="$parent.mdRowSelection">
|
||||
<md-table-cell class="md-table-selection" v-if="$parent.mdRowSelection">
|
||||
<md-checkbox v-model="checkbox" @change="select"></md-checkbox>
|
||||
</td>
|
||||
</md-table-cell>
|
||||
|
||||
<slot></slot>
|
||||
</tr>
|
||||
|
|
@ -37,10 +37,12 @@
|
|||
},
|
||||
handleSingleSelection(value) {
|
||||
this.setSelectedRow(value, this.index);
|
||||
this.$parent.$children[0].checkbox = this.$parent.numberOfSelected >= this.$parent.numberOfRows;
|
||||
this.$parent.$children[0].checkbox = this.$parent.numberOfSelected === this.$parent.numberOfRows;
|
||||
},
|
||||
handleMultipleSelection(value) {
|
||||
this.$parent.$el.classList.add(transitionClass);
|
||||
if (this.$parent.numberOfRows > 25) {
|
||||
this.$parent.$el.classList.add(transitionClass);
|
||||
}
|
||||
|
||||
this.$parent.$children.forEach((row) => {
|
||||
row.checkbox = value;
|
||||
|
|
|
|||
Loading…
Reference in a new issue