3

I have a simple table to which the user can add rows. The interface is very similar to this:
https://jsfiddle.net/fgu4q8j0/1/

<div id="app">
  <table class="list">
    <tr v-for="(task,index) in tasks">
      <td>{{index+1}}.</td>
      <td>{{task.text}}</td>
    </tr>
  </table>
  <input type="text" v-model="newTask" />
  <button type="button" @click="tasks.push({text: newTask})">Add</button>
</div>

new Vue({    
  el: "#app",
  data: {
    newTask: "",
    tasks: [{text: 'task1'}, {text: 'task2'}]
  }
});

I want to create highlight effect when a new row is added, which decays slowly - very similar to the orange highlight effect that Stack Overflow has when you click a url that contains a hash (#) to a specific answer/comment.
As I see, Stack Overflow uses jQuery for animation. I look for a CSS only solution, hopefully without doing anything more than tasks.push(..), and maybe integrates into vue transition system.

2 Answers 2

2

You can just do something simple like this by using animation and adding a class for your new items:

new Vue({
  el: "#app",
  data: {
    newTask: "",
    tasks: [{
      text: 'task1'
    }, {
      text: 'task2'
    }]
  }
});
tr.new {
  animation: blink 2s ease;
}

@keyframes blink {
  0% {
    background-color: yellow;
  }
  100% {
    background-color: white;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
  <table class="list">
    <tr v-for="(task,index) in tasks" :class="{new: task.new}">
      <td>{{index+1}}.</td>
      <td>{{task.text}}</td>
    </tr>
  </table>
  <input type="text" v-model="newTask" />
  <button type="button" @click="tasks.push({text: newTask, new: true})">Add</button>
</div>

If you don't want to track state like this, then you'll have to do things properly and use Vue's <transition-group>, and if you check this, it says you need the template option to get around the browser's behavior of stripping tags inside table...so you might create a component like this:

Vue.component('tasks-list', {
  template: `
    <div>
      <table class="list">
        <transition-group name="blink">
          <tr v-for="(task,index) in tasks" :key="index">
            <td>{{index+1}}.</td>
            <td>{{task.text}}</td>
          </tr>
        </transition-group>
      </table>
      <input type="text" v-model="newTask" />
      <button type="button" @click="tasks.push({text: newTask, new: true})">Add</button>
    </div>`,
  data() {
    return {
      newTask: "",
      tasks: [{
        text: 'task1'
      }, {
        text: 'task2'
      }]
    }
  }
})
new Vue({
  el: "#app",
});
.blink-enter-active,
.blink-leave-active {
  transition: background 2s ease;
  background-color: white;
}

.blink-enter,
.blink-leave-to {
  background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
  <tasks-list></tasks-list>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

This is good, but I don't like the need for a new data member for added rows. Maybe it is better to create a directive for this? What will be more efficient/performant?
1

You can add a <tbody name="fade" is="transition-group"> tag around your tr's to make it work with table rows. See this Github issue.

new Vue({    
  el: "#app",
  data: {
    newTask: "",
    tasks: [{text: 'task1'}, {text: 'task2'}]
  }
});
body {font-size: 20px}

.fade-enter-active, .fade-leave-active {
  background-color: none;
  transition: all 2s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  background-color: yellow;
}
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>

<div id="app">
  <table class="list">
    <tbody name="fade" is="transition-group">
      <tr v-for="(task,index) in tasks" :key="index">
        <td>{{ index + 1 }}.</td>
        <td>{{ task.text }}</td>
      </tr>
    </tbody>
  </table>
  <input type="text" v-model="newTask" />
  <button type="button" @click="tasks.push({text: newTask})">Add</button>
</div>

2 Comments

Can't use list, I do need the table. And I actually prefer this solution, rather than creating a data member just for the transition. I mean, with jQuery after I call .animate(), there is no data or any side effects around after the effect is over
I've edited the answer to make it work with a table by adding a <tbody name="fade" is="transition-group"> tag.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.