1

I have a data structure here which i have divided into headers and the items. I am trying to apply a custom sort for which i have the logic down and i have created a method for it but i am not able to figure out how to apply that sort methods based on the name and grades individually. Here is a link to the codepen.

new Vue({
  el: '#app',
  data() {
    return {
      headers: [{
          text: 'Name',
          value: 'Name'
        },
        {
          text: 'Grades',
          value: 'grades'
        },
      ],
      labels: ['Andy', 'Max', 'John', 'Travis', 'Rick'],
      Grades: [99, 72, 66, 84, 91]
    }
  },
  computed: {
    tableItems() {
      let items = [],
        this.labels.forEach((label, i) => {
          let item = {}
          item.name = label
          item.grades = this.Grades[i]
          items.push(item)
          console.log(items)
        })
      return items
    }
  },
  methods: {
    sortBy(prop) {
      this.tableItems.sort((a, b) => a[prop] < b[prop] ? -1 : 1)
    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet" />
<div id="app">
  <v-app id="inspire">
    <v-container>
      <v-layout>
        <v-flex v-for="(header, i) in headers" :key="header.text" xs4 py-1>
          <span>{{ header.text }}
                    <v-icon small @click="sortBy(this.labels)">arrow_upward</v-icon>  
                  </span>
        </v-flex>
        <v-layout v-for="item in tableItems" :key="item.name">
          <v-flex xs4 py-1>
            <span>{{ item.name }}</span>
          </v-flex>
          <v-flex xs4 py-1>
            <span>{{item.grades}}</span>
          </v-flex>

        </v-layout>
      </v-layout>
    </v-container>
  </v-app>
</div>

Now while keeping the data structure and everything the way it is, how can i make the method on the v-icon work for grades and name individually?

1 Answer 1

1

Here are a few things I did to make it work.

  • Define a sortKey on the basis of which your data will be sorted
  • Pass the sortKey as an argument when you click on your span
  • When computing your tableItems use the sort key to sort your data

Look for the comments in the code below

<div id="app">
    <v-app id="inspire">
        <v-container>
        <v-layout>
            <v-flex v-for="header in headers" :key="header.text" xs4 py-1>
            <span>
                {{ header.text }}
                <v-icon small @click="sortBy(header.value)">arrow_upward</v-icon>
                ***** changed the value for name (from Name to name) ****
            </span>
            *** everything else is the same ***
        </v-layout>
        </v-container>
    </v-app>
</div>  

The script looks like this

    <script>
    export default {
      name: "app",
      data() {
        return {
          headers: [
            { text: "Name", value: "name" }, // changed this to name
            { text: "Grades", value: "grades" }
          ],
          labels: ["Andy", "Max", "John", "Travis", "Rick"],
          Grades: [99, 72, 66, 84, 91],
          sortKey: "" // added a sortKey,
        };
      },
      computed: {
        tableItems() {
          let retVal = this.labels.map((label, i) => {
            return {
              name: label,
              grades: this.Grades[i]
            };
          });
          // if there is a sortKey use that
          if (this.sortKey) {
            retVal.sort((a, b) =>
              a[this.sortKey] < b[this.sortKey] ? -1 : 1
            );
          }
          return retVal;
        }
      },
      methods: {
        sortBy(prop) {
          // assign sortKey here, this assignment will retrigger the computation
          this.sortKey = prop;
          console.log(prop);
        }
      }
    };
    </script>

************* EDIT *****************

add in a direction variable for your sorting order (1 is ascending, -1 is descending)

so your data would look like

data() {
    return {
        headers: [
            { text: "Name", value: "name" }, // changed this to name
            { text: "Grades", value: "grades" }
        ],
        labels: ["Andy", "Max", "John", "Travis", "Rick"],
        Grades: [99, 72, 66, 84, 91],
        sortKey: "" // added a sortKey,
        direction: 1 // for ascending order
    };
},

now in your program, if you are clicking on the same thing, you need to change your ascending or descending state, do that in your method

methods: {
    sortBy(prop) {
        // if the sortKey was prop to begin with
        if (this.sortKey === prop) {
            this.direction *= -1 // change direction to -ve or positive
        }
        // assign sortKey here, this assignment will retrigger the computation
        this.sortKey = prop;
        console.log(prop);
    }
}

Finally, use your direction in the sorting

computed: {
    tableItems() {
        let retVal = this.labels.map((label, i) => {
            return {
                name: label,
                grades: this.Grades[i]
            };
        });
        // if there is a sortKey use that
        if (this.sortKey) {
            retVal.sort((a, b) =>
                this.direction * // here multiply by the direction
                (a[this.sortKey] < b[this.sortKey] ? -1 : 1)
            );
        }
        return retVal;
    }
},

And You will be done

Sign up to request clarification or add additional context in comments.

3 Comments

Oh wow. this seems to work, but what if i wanna set it both to ascending and descending. and not just one way? sorry, i should have added this is the question.
@Somethingwhatever I have added an edit section. Let me know if you need more help :)
Appreciate all the help. Thank you so much :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.