I have a md-table in which I can filter the rows by the name of course, the filter works fine but as soon as I click on on the column name, the rows are not sorted
you should be able to sort them like in this sandbox https://codesandbox.io/s/n7l7o742qm?module=App.vue
but if you try my code https://codesandbox.io/s/vue-material-search-and-empty-state-forked-6bb48?file=/App.vue
the sort functionality won't work
HTML
<md-table
v-model="filteredRepetitions"
md-sort="corso"
md-sort-order="asc"
md-card
md-fixed-header
>
<md-table-toolbar>
<h1 class="md-title">With auto select and alternate headers</h1>
<md-field md-clearable class="md-toolbar-section-end">
<md-input placeholder="Search by course..." v-model="search"/>
</md-field>
</md-table-toolbar>
<md-table-row
class="md-primary"
slot="md-table-row"
slot-scope="{ item }"
>
<md-table-cell md-label="Corso" md-sort-by="corso">{{ item.corso }}</md-table-cell>
<md-table-cell md-label="Docente" md-sort-by="docente">{{ item.docente }}</md-table-cell>
<md-table-cell md-label="Data" md-sort-by="timeSlot.data">{{ item.timeSlot.data }}</md-table-cell>
<md-table-cell
md-label="Fascia oraria"
md-sort-by="timeSlot.fasciaOraria"
>{{ item.timeSlot.fasciaOraria }}</md-table-cell>
<md-table-cell md-label="Stato" md-sort-by="stato">{{ item.stato }}</md-table-cell>
</md-table-row>
</md-table>
JS
const toLower = text => text.toString().toLowerCase();
export default {
data() {
return {
search: '',
repetitions2: [
{
corso: 'Programmazione 3',
docente: 'Liliana Aridissono',
timeSlot: {
fasciaOraria: '15:00-16:00',
data: '2020-09-17'
},
stato: 'attiva'
},
{
corso: 'Python',
docente: 'Marco Amedura',
timeSlot: {
fasciaOraria: '17:00-18:00',
data: '2020-03-17'
},
stato: 'noattiva',
},
{
corso: 'Matematica Discreta',
docente: 'Vincenzo Bellomo',
timeSlot: {
fasciaOraria: '16:00-17:00',
data: '2020-02-17'
},
stato: 'noattiva',
},
{
corso: 'Algoritmi',
docente: 'Patti Viviana',
timeSlot: {
fasciaOraria: '16:00-17:00',
data: '2020-10-17'
},
stato: 'attiva',
},
{
corso: 'Analisi',
docente: 'Pinco Pallo',
timeSlot: {
fasciaOraria: '18:00-19:00',
data: '2020-10-26'
},
stato: 'attiva',
}
]
}
},
methods: {
},
computed: {
filteredRepetitions: {
get: function () {
return this.repetitions2.filter(item => toLower(item.corso).includes(toLower(this.search)))
},
set: function (array) {
// what should i say?
}
}
},
}
BONUS QUESTION: is it possible not to filter only for a particular attribute (for instance now I can filter only by course name)
After playing around with <md-table>
a bit more, it turns out you don't actually need computed for sortColumn
and sortOrder
. You do need to use .sync
modifier, though, as outlined in the docs.
And you have to provide an empty setter (md-table
will try to assign to the computed when it's changed). However, you don't need to assign anything, as sortColumn
and sortOrder
change accordingly and your getter reacts to those changes.
I added a watch
which resets sortOrder
every time the sortColumn
is changed - other than that, it's pretty clean.
Relevant code:
import { sortBy } from 'lodash-es';
{
data: () => ({
searchTerm: "",
searchColumn: "corso",
sortColumn: "corso",
sortOrder: "asc",
items: [...]
}),
computed: {
filteredItems() {
return this.items.filter(
item => this.searchColumn
.split(".")
.reduce((obj, prop) => obj[prop], item)
.toLowerCase()
.indexOf(this.searchTerm.toLowerCase()) > -1
);
},
orderedItems: {
get: function() {
return sortBy(this.filteredItems, this.sortColumn);
},
set: () => {}
}
},
watch: {
sortColumn() {
this.$nextTick(() => (this.sortOrder = "desc"));
}
},
}