Abraham Felix
Abraham Felix

Reputation: 109

how can i sort table using array data in vue

My attempt was trying to sort the outcome of the data in the method, but later I want to implement a button in the table header, but I can't even get the sorting part of a, b solution to work with the data from rows = []. I can use the vuetify table but I want to learn how I can do it manually...

in simple words, I want to sort by this row array Amount_Raised_Millions

 <template>
<div class="container-fluid">
        <div class="row mb-10">
            <main role="main" class="col-md-12 ml-sm-auto col-lg-12 pt-3 px-4">
                <div class=" pb-2 ma-3 ">
                    <h2 class="center">Funding</h2>
                    <v-divider></v-divider>
                </div>
                <div class=" table-responsive">
                <table class="table table-striped mb-0">
                    <thead>
                    <tr>
                        <th>Name</th>
                        <th>Funding Date</th>
                        <th>Amount Raised</th>
                        <th>Round</th>
                        <th>Total Raised</th>
                        <th>Founder</th>
                        <th>Est.</th>
                        <th>Location</th>
                        <th>Lead Investor</th>
                        <th class="d-none">Employees</th>
                    </tr>
                    </thead>
                    <span class="table-span">
                        <v-row class="center mt-15" v-if="loading">
                            <v-col
                                cols="12"
                                >
                                <v-progress-circular
                        :size="150"
                                color="blue"
                                indeterminate
                        > Loading...
                                </v-progress-circular>
                        </v-col>
                </v-row>
                    <tbody >
                        <Row v-bind:key="row.id" v-for="row in rows" v-bind:row="row" />
                    </tbody>
                </span>
                </table>
                </div>

            </main>
        </div>
    </div>
</template>

<script>

import Row from '@/components/Row.vue';
const { GoogleSpreadsheet } = require('google-spreadsheet');
const creds = require('@/client_secret.json');
    export default {
        name: "Sheet",
        components: {
            Row
        },
        props: ["sheet"],
        data() {
            return {
                rows: [],
                loading: true,
            }
        },
        methods:{
            async accessSpreadSheet() {
                const doc = new GoogleSpreadsheet(process.env.VUE_APP_API_KEY);
                await doc.useServiceAccountAuth(creds);
                await doc.loadInfo();
                const sheet = doc.sheetsByIndex[0];
                const  rows = await sheet.getRows({
                    offset: 1
                })
                this.rows = rows.sort((a,b)=>a.Name-b.Name);
                this.loading = false;
        //console.log(rows)
            }
        },
        created() {
            this.accessSpreadSheet();
            // testing console.log(process.env.VUE_APP_API_KEY)
        },
        //computed() {
            //return this.rows.sort((a,b)=>a.row.Name-b.row.Name);
        //}

    }
</script>

Upvotes: 0

Views: 1836

Answers (2)

Firstly, sort existing array

const items = ref(tableData);
const sortedItems = computed(() => {
 return items.value.sort((a, b) => b - a);
});

Then define direction

const ascending = ref(false);

And create function

function sortTable(col) {
  if (sortColumn.value === col) {
     ascending.value = !ascending.value;
  } else {
     ascending.value = true;
     sortColumn.value = col;
  }

 sortedItems.value.sort((a, b) => {
   if (a[col] < b[col]) {
    return ascending.value ? -1 : 1;
   } else if (a[col] > b[col]) {
     return ascending.value ? 1 : -1;
   }
  return 0;
 });
}

And in the template

<tr v-for="item in sortedItems" :key="item">

Upvotes: 0

Emīls Gulbis
Emīls Gulbis

Reputation: 2070

Use computed properties to sort fetched rows

Added example for plain table row sorting (check out by clicking on table column names)

new Vue({
  el: "#app",
  data() {
    return {
      sortBy: false,
      rows: [],
    }
  },
  computed: {
    computedRows() {
      if(this.sortBy) {
        return [...this.rows]
          .sort((a, b) => a[this.sortBy] - b[this.sortBy])
      }
      return this.rows
    }
  },
  methods: {
    fillRows() {
      for(var i = 0; i < 10; i++) {
        this.rows.push({
          name: faker.name.findName(),
          date: faker.date.past(),
          amount: faker.datatype.number(),
          round: faker.datatype.number(5),
          total: faker.datatype.number(),
          founder: faker.name.findName(),
          est: faker.date.past(),
          location: faker.address.city(),
          investor: faker.name.findName(),
          employees: faker.datatype.number(50)
        })
      }
    }
  },
  mounted() {
    this.fillRows()
  },
  
  filters: {
    date(d) {
      return [
        d.getFullYear(),
        d.getMonth(),
        d.getDay()
       ].join('/')
    },
    
    year(d) { return d.getFullYear() }
  }
})
table td, table th { padding: 10px; border:1px solid #eee }
<script src="https://rawgit.com/Marak/faker.js/master/examples/browser/js/faker.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <table class="table table-striped mb-0">
    <thead>
      <tr>
        <th @click="sortBy = 'name'">Name</th>
        <th @click="sortBy = 'date'">Funding Date</th>
        <th @click="sortBy = 'amount'">Amount Raised</th>
        <th @click="sortBy = 'round'">Round</th>
        <th @click="sortBy = 'total'">Total Raised</th>
        <th @click="sortBy = 'founder'">Founder</th>
        <th @click="sortBy = 'est'">Est.</th>
        <th @click="sortBy = 'location'">Location</th>
        <th @click="sortBy = 'investor'">Lead Investor</th>
        <th @click="sortBy = 'employees'">Employees</th>
      </tr>
    </thead>

    <tbody >
      <tr v-for="row in computedRows">
        <td>{{ row.name }}</td>
        <td>{{ row.date | date }}</td>
        <td>{{ row.amount }}</td>
        <td>{{ row.round }}</td>
        <td>{{ row.total }}</td>
        <td>{{ row.founder }}</td>
        <td>{{ row.est | year }}</td>
        <td>{{ row.location }}</td>
        <td>{{ row.investor }}</td>
        <td>{{ row.employees }}</td>
      </tr>
    </tbody>
  </table>
</div>

Upvotes: 1

Related Questions