Tom
Tom

Reputation: 87

Highlight newly inserted row in Vue.js

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>

Upvotes: 2

Views: 849

Answers (2)

Daniel Elkington
Daniel Elkington

Reputation: 3665

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

Upvotes: 1

Jakub A Suplicki
Jakub A Suplicki

Reputation: 4801

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.

Upvotes: 1

Related Questions