1

Let's say I have a component which repeats with a v-for loop like so:

<hotel v-for="(hotel, index) in hotels"></hotel>

And my hotels array would look like so:

[
    {
        name: false   
    }, 
    {
        name: false   
    },  
    {
        name: true   
    }, 
    {
        name: true   
    }
]

How could I perform an action when my v-for loop encounters the property name set to true only on the very first time it encounters this truthy property?

I know I could probably cache a property somewhere and only run something once and not run again if it has been set but this does not feel efficient.

Stephan-v
  • 19,255
  • 31
  • 115
  • 201

3 Answers3

3

Use a computed to make a copy of hotels where the first one has an isFirst property.

computed: {
    hotelsWithFirstMarked() {
        var result = this.hotels.slice();
        var first = result.find(x => x.name);

        if (first) {
            first.isFirst = true;
        }
        return result;
    }
}
Roy J
  • 42,522
  • 10
  • 78
  • 102
  • I am guessing I should also use `this.$set()` to maintain reactivity if I want to set a non-existent property? Instead of simply setting the property directly, or is this not the case here? – Stephan-v Sep 13 '17 at 14:54
  • 1
    Not the case in a computed, which I had to remind myself of, twice, while writing it. – Roy J Sep 13 '17 at 14:57
  • 1
    By the way you are using `Object.assign()` and in turn call `result.find` (an array prototype method) on an Object. I understand the concept but perhaps change it to working code for any future reference/other users? – Stephan-v Sep 14 '17 at 07:42
2

Just use computed source

HTML

 <div v-for="(hotel, index) in renderHotels"></div>

JS

    export default {
        name: 'message',
         data () {
           return{
                  hotels:[
    {
        name: false   
    }, 
    {
        name: false   
    },  
    {
        name: true   
    }, 
    {
        name: true   
    }
] ,
     wasFirst : false
              }
  
        },
        methods:{
            
        },
        computed:{
         renderHotels(){
           return this.hotels.map((hotel)=>{
             if(hotel.name && !this.wasFirst){
                  this.wasFirst = true;
                  alert('First True');
                   console.log(hotel);
               }
          })
        }
}
      }
tony19
  • 125,647
  • 18
  • 229
  • 307
Omri Lugasi
  • 337
  • 3
  • 16
  • 1
    You cannot make computeds with arguments. You mean a method. This will also be a little brittle on re-render. – Roy J Sep 13 '17 at 14:41
  • Adding to Roy J.. see this topic for an explanation https://stackoverflow.com/questions/40522634/can-i-pass-p – enriqg9 Sep 13 '17 at 14:42
0

Best way is to use filter function.

    data() {
     return {
      firstTime: false,
     };
    },
    filters: {
        myFunc: function (hotel) {
          if (hotel.name && !this.firstTime) {
             //perform some action
             this.firstTime = true;
          }
        }
    }

<hotel v-for="(hotel, index) in hotels | myFunc"></hotel>
Georgi Antonov
  • 1,581
  • 21
  • 40