How to blink specific row for 2 times using Vue.js & Vuetify?

Viewed 547

After creating a record, I showed an alert green message if API returns 200 OK, and red otherwise. Right now, it is working perfectly I used Vuex + Vuetify Snackbar.

this.notifcationData = {
    color: 'green',
    text: campaign.name + ' - deleted successfully !'
}



<v-snackbar timeout="1000" v-model="notification" absolute top :color="notifcationData.color" outlined right>
    <strong>
        {{ notifcationData.text }}
    </strong>
</v-snackbar>

enter image description here

I want to improve the UX one more notch. I would like to blink that specific row for 1 sec (2 times).

I know I have access to the campaign.name

How do I achieve that in Vue.js ?

2 Answers

you can use item-class prop in your v-data-table to achieve the effect.

according to DOC for this prop we have:

Property on supplied items that contains item’s row class or function that takes an item as an argument and returns the class of corresponding row

so you can pass this prop a function that based on the conditions met, returns a class like blink to be applied to the specified row.

here is a demo of this feature: (please click on Full page after running the code snippet below to see the effect clearly)

Vue.config.productionTip = false;
Vue.config.devtools = false;

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data() {
    return {
      rowToBlink: null,
      items: [{
          id: 1,
          name: 'Frozen Yogurt',
          calories: 159,
        },
        {
          id: 2,
          name: 'Ice cream sandwich',
          calories: 237,
        },
        {
          id: 3,
          name: 'Eclair',
          calories: 262,
        },
        {
          id: 4,
          name: 'Cupcake',
          calories: 305,
        },
      ],
      headers: [{
          text: 'Dessert',
          value: 'name',
        },
        {
          text: 'Calories',
          value: 'calories'
        },
      ],
    };
  },
  methods: {
    blink(item) {
      if (item.id === this.rowToBlink) return 'blink';
      return '';
    }
  },
});
.blink {
  animation: blinking ease-out 1s 2;
}

@keyframes blinking {
  0% {
    background-color: #06c3d1;
  }
  100% {
    background-color: #fff;
  }
}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>

<div id="app">
  <v-app>
    <v-container>
      <v-row class="pa-5">
        <v-autocomplete v-model="rowToBlink" outlined label="select row to blink" :items="items" item-text="name" item-value="id"></v-text-field>
      </v-row>
      <v-row class="px-5">
        <v-data-table hide-default-footer :headers="headers" :items="items" :item-class="blink"></v-data-table>
      </v-row>
    </v-container>
  </v-app>
</div>

for the sake of this example I bind the data table items array to a select box where you can select the item you want and passed a method called blink to the data table's item-class prop.

what this function does is that it checks if the selected item's id from the select box matches the data table's item id then returns a class called 'blink' for the specified item (row) in the table, otherwise it returns no class name.

the blink effect is taken care of in the .blink css class where you can play with the css features (time duration, delay, easing function, ...) to achieve the desired look.

some idea on how to implement this in your real app situation would be to store the campaign name in a variable after the api call returns like:

async apiCall(someArg, campaignName) {
 const res = await apiFn(someArg);
 // store the campaign name in a variable in data object if the res is what you are looking for
 if (res) this.campaignName = campaignName;
}

then your item-class function would be something like this:

blink(item) {
 if (item.name === this.campaignName) return 'blink';
 return '';
}

You would do this with transitions.

Theres actually a few transitions to chose from in vue.js, Mines would be the CSS transition or animate.

Vue.js Transitions

With Vue.js’ transition system you can apply automatic transition effects when elements are inserted into or removed from the DOM. Vue.js will automatically add/remove CSS classes at appropriate times to trigger CSS transitions or animations for you, and you can also provide JavaScript hook functions to perform custom DOM manipulations during the transition.

EXAMPLE:

On your element set the transition you want to use or a new transition name that you have yet to create in CSS.

transition="blink"

You then want to set three CSS rules .blink-transition, .blink-enter and .blink-leave.

.blink-transition {
  transition: all 1s ease;
  background-color: green;
}

.blink-enter, .blink-leave {
  background-color: white;
}

and that's it. the above would cause an element to blink for one second.

My example probably isn't idle for your blinking in which case I'd use CSS keyframes. Theres an example in the docs

UPDATE:

Vue.js now has a transition component.

Vue.js 2 Tranitions

Instead of a transition parameter you now use a transition element by wrapping what it is you want to animate.

<transition name="blink"> </transition>
Related