Search code examples
arraysvue.jssorting

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>

Solution

  • 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>