Highlight newly inserted row in Vue.js

Viewed 432

I am fetching the JSON data(Orders) from REST API and displaying in a dynamic HTML table using Vue js. I have a "Print" button for each row in the table. The purpose of the button is printing the data of the row in a structure, basically a bill. For that, I want to highlight the newly added row until the Print button is clicked by the user. How do I achieve this? I'm refreshing the table every minute. This is my code.

<tr v-for="orders, index in orders">
  <th scope="row">{{ index + 1 }}</th>
    <td>{{ orders.id }}</td>
    <td>{{ orders.billing.first_name + " " +orders.billing.last_name }}</td>
    <td>{{ orders.date_created }}</td>
    <td>{{ orders.billing.phone}}</td>
    <td>{{ orders.billing.address_1 + ", " + orders.billing.address_2 + ", " + orders.billing.city + orders.billing.postcode }}</td>
    <td>{{ orders.line_items.name}}</td>
    <td>{{ orders.total}}</td>
    <td><button class="btn btn-primary" (click)="printBill(data)">Print</button></td>
  </tr>
</tbody>
</table>
</div>
<script>
var app = new Vue({
  el: '#app',
  data: {
    orders: []
  },
  mounted: function() {
    axios.get('https://localhost/Site/wp-json/wc/v3/orders?consumer_key=KEY&consumer_secret=KEY1')
      .then(response => {
        this.orders = response.data;
        console.log(response);
       })
       .catch(error => {
         console.log(error);
        });
     },      
  })
</script>
2 Answers

I wrote a small example, have a look:

<template>
  <div id="app">*
    <tr
      v-for="(order, index) in orders"
      :key="index"
      :class="{highlight: orders[index].isPrinted === undefined}"
    >
      <th scope="row">{{ index + 1 }}</th>
      <td>{{ order.name }}</td>
      <td>{{ order.something}}</td>
      <td>
        <button class="btn btn-primary" @click="printBill(index)">Print</button>
      </td>
    </tr>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      orders: []
    };
  },
  methods: {
    printBill(index) {
      //code to print the bill

      //change flag
      this.$set(this.orders[index], "isPrinted", true);
    }
  },
  mounted() {
    //axios request - data sample
    this.orders = [
      {
        name: "first",
        something: "whatever"
      },
      {
        name: "second",
        something: "whatever"
      },
      {
        name: "third",
        something: "whatever"
      },
      {
        name: "fourth",
        something: "whatever"
      },
      {
        name: "fifth",
        something: "whatever"
      }
    ];
  }
};
</script>

<style>
.highlight {
  background-color: blue;
  color: white;
}
th {
  width: 20%;
}
td {
  width: 20%;
}
</style>

You can run it here.


As you can see that I am adding a flag to elements in orders array whenever printBill method runs.

By tracking newly added property we can conditionally display highlight class.

Add an isPrinted flag to each row of data, making sure you retain this if rows had been previously flagged. Also, call the API every minute.

  mounted: function() {
    // Call the API the first time
    this.refreshData()
    // Then call the API every minute
    this.setIntervalId = setInterval(this.refreshData, 60000)
  },
  beforeDestroy: function() {
    // Stop refreshing data after the component is destroyed!
    clearInterval(this.setIntervalId)
  }
  methods: {
    // Extract refresh logic into a method
    refreshData () {
      axios.get('https://localhost/Site/wp-json/wc/v3/orders?consumer_key=KEY&consumer_secret=KEY1')
      .then(response => {
        // Note the orders we previously flagged as printed, so we can reapply the flag after refreshing
        const previouslyFlaggedIds = this.orders.filter(x => x.is_printed).map(x => x.id);
        this.orders = response.data.map(x => ({...x, is_printed: previouslyFlaggedIds.find(y => y === x.id) != null}));
       })
       .catch(error => {
         console.log(error);
      });
    }
  }

Use this to style the rows

<tr
      v-for="(order, index) in orders"
      :key="order.id"
      :class="{highlight: !order.is_printed}"
    >

Set is_printed when rows are printed.

<td><button class="btn btn-primary" @click="printBill(order)">Print</button></td>
methods: {
    printBill(order) {
      order.is_printed = true
    }
  }
Related