1

Is it possible to evaluate the v-if directive only once on an element and ignore any changes in the boolean expression after that? For example:

<div v-for="item in items" v-bind:key="item.id">
     <span>{{ item.name }}</span>
     <span>{{ item.status }}</span>
     <span v-if="match.lastUpdateEpoch">Last Changed {{ getDateFromEpoch(match.lastUpdateEpoch) }}</span>
</div>

I only want the third and final span to be displayed if the value is non-zero when the items are initially loaded and rendered but I only want the v-if expression to be evaluated once. So, if the value of match.lastUpdateEpoch is initially 0, it won't be displayed. But if the value changes to something non-zero at any stage, I still don't want it to be displayed. It should only respect the first evaluation. Is this possible using a directive or something else that doesn't involve me creating additional state variables? I am aware of v-once but that only means the value itself will not be re-rendered when it is updated, the show/hide expression will still be evaluated.

The items are initially set based on some JSON data returned from my server e.g.

var VUE = new Vue({
    el: '#vue-root',    
    data: {
        items: [],
        ...

...
var items = loadItems(); // ajax server call 
VUE.items = items; 
// each item is an object e.g.  
// {name:'a',status:'1',lastUpdateEpoch: 0}
// {name:'b',status:'2',lastUpdateEpoch: 123456789}
1
  • "So, if the value of match.lastUpdateEpoch is initially 0" how do you set this value initially? Inside the created() or mounted() method? Commented May 15, 2020 at 13:37

1 Answer 1

2

You could use the v-once directive, which renders the element only once. In addition, you'd have to change v-if to v-show to perform the initial rendering (and only rendering).

<span v-show="item.lastUpdateEpoch" v-once>

new Vue({
  el: '#app',
  data() {
    return {
      items: [
        { id: 100, name: 'John', status: 'Active', lastUpdateEpoch: 0 },
        { id: 200, name: 'Bob', status: 'Idle', lastUpdateEpoch: new Date() },
        { id: 300, name: 'Charlie', status: 'Idle', lastUpdateEpoch: 0 },
      ]
    }
  },
  methods: {
    getDateFromEpoch(epoch) {
      if (!epoch) return ''
      return typeof epoch == 'string' ? epoch : epoch.toDateString()
    }
  }
})
.item {
  margin: 1rem;
}
<script src="https://unpkg.com/[email protected]"></script>

<div id="app">
  <div v-for="item in items" v-bind:key="item.id" class="item">
    <span>{{ item.name }}</span>
    <span>{{ item.status }}</span>
    <span v-show="item.lastUpdateEpoch" v-once>Last Changed {{ getDateFromEpoch(item.lastUpdateEpoch) }}</span>
    <div>
      <input v-model="item.lastUpdateEpoch" type="date">
    </div>
  </div>
  <pre>{{ items }}</pre>
</div>

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

Comments

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.