4

Using vue.js 2, inside a for loop, I need to render a row only if the current iterated item passes some test.

The test is complex so a simple v-if="item.value == x" wont do.

I've written a function named testIssue that accepts the item and returns true or false and tried to use that is av-if like this:

<template v-for="issue in search_results.issues">
  <tr v-if="testIssue(issue)">
     ....
  </tr>
</template>


var releaseApp = new Vue({
  el: '#release-app',
  methods: {
    testIssue: function(issue) {
      console.log(issue);
      console.log('test');
    },
  },
  mounted: function() {},
  data: {
    search_results: {
      issues: []
    },
  }
});

However, testIssue is never called.

If I change the line to <tr v-if="testIssue">, the function is called but then I dont have the issue variable that I need to test.

I also tried <tr v-if="releaseApp.testIssue(issue)">

How can I call a function in a v-if declaration inside a for loop and pass the current item?

3 Answers 3

3

First of all you can't do v-for on a <template> tag as you can have only one element per template.

You can add a v-if on the same element as v-for, and it just won't render the element that doesn't pass the v-if. If it's a spearate component per row then it's better to do v-for in parent component and pass the issue by props to child component.

Parent:

<child-comp v-for="issue in search_results.issues" v-if="testIssue(issue)">
</child-comp>

Child:

<template>
  <tr>
    {{issue}}
  </tr>
</template>
Sign up to request clarification or add additional context in comments.

4 Comments

Seeing the code @delightedDOD is not using single file components where template element is present. he just doing it the plain javascript way. So v-for on template tag is possible as it is inside some parent element which has id #release-app. See this fiddle ( jsfiddle.net/r_vamsi_krishna/50pgoo5u/3)
Then yes, he can do it also without child components.
what do you mean by without child components
inside his template elementt he just wants <tr> to not be displayed. By placing v-if on the template element itself will conditionally display the whole template element, i think he just wants to conditionally display <tr> inside template element.
2

Your scenario works with a similar example in this fiddle.

But you can try it this way also:

You can create a custom directive named v-hide and pass issue to it as its value.

Then in the directive you can test for testIssue() and set the particular element's display to none

<template v-for="issue in search_results.issues">
  <tr v-hide="issue">
     ....
  </tr>
</template>


var releaseApp = new Vue({
  el: '#release-app',
  directive:{
    hide: {
        bind(el, binding, Vnode){
            var vm = Vnode.context;
            var issue = binding.value;
            if(vm.testIssue(issue)){
                el.style.display = 'none';
            }
        }
    }
  },
  methods: {
    testIssue: function(issue) {
      console.log(issue);
      console.log('test');
    },
  },
  mounted: function() {},
  data: {
    search_results: {
      issues: []
    },
  }
});
 

1 Comment

You're right that fiddle does work, and I was sure I had done this before without issue, that proves it. There must be something else going on in my code causing my issue. Thank you, gonna dig some more
1

You can also try creating a computed item that makes use of the filter method so that you have an array where all elements pass the test function before actually rendering (in this case, just returning odd numbers):

https://codepen.io/aprouja1/pen/BZxejL

computed:{
    compIssues(){
      return this.search_results.issues.filter(el => el%2===1)
    }
  },

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.