Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

v-for and v-if not working together in vue.js

A form is used to submit text and two options which tell vue which column to display the text in. When the col2 radio button is checked the submitted text should display in column 2. This is not happening, on column 1 text is displaying.

I have two radio buttons which should pass the value 'one' or 'two' to a newInfo.option On submnit a method pushed the form data to the array 'info'.

<input type="radio" id="col1" value="one" v-model="newInfo.col">
<input type="radio" id="col2" value="two" v-model="newInfo.col">

This data is being pushed to the array 'info' correctly and I can iterate through it. I know this is working because I can iterate through the array, an console.log all the data in it. All the submitted form data is there.

Next I iterate through this array twice in the template. Once for info.col==="one" and the other iteration should only display when info.col==="two". I am using a v-for and v-if together, which the vue.js documentation says is ok to do,

https://v2.vuejs.org/v2/guide/conditional.html#v-if-with-v-for

<div class="row">
            <div class="col-md-6">
                <ol>
                    <li v-for="item in info" v-if="item.col==='one'">
                        text: {{ item.text }}, col: {{ item.col }}
                    </li>
                </ol>
            </div>
            <div class="col-md-6">
                <ol>
                    <li v-for="item in info" v-if="!item.col==='two'">
                        text: {{ item.text }}, col: {{ item.col }}
                    </li>
                </ol>
            </div>
        </div>

The full vue.js code is on github here

And it is running on gh-pages here

like image 534
Shane G Avatar asked Feb 22 '18 17:02

Shane G


People also ask

Why is it recommended not to use V-if and V-for directives together on the same element in VUE JS?

It's not recommended to use v-if and v-for on the same element due to implicit precedence.

Can we use V-if and V-show together?

If v-if == true and v-show changes from true to false , the leave transition occurs as expected. If v-show== true and v-if changes from true to false , the element is immediately removed, no transition occurs. My use case for this is using both v-if and v-show around media ( img , video ).

What is the difference of using V-if V else if V else or V-show only?

The key difference is that v-if conditionally renders elements and v-show **conditionally displays **elements. This means that v-if will actually destroy and recreate elements when the conditional is toggled. Meanwhile, v-show will always keep the element in the DOM and will only toggle its display by changing its CSS.

How does v-If work Vue?

The v-if directive is used to conditionally render a block meaning the block with the v-if attribute will only be produced if the directive's expression returns a true value. If the expression produces an invalid result (for example, null , 0 , empty string, false ), the element is deleted from the DOM.

What's wrong with vuejs V-for?

Don't do it again. The problem with this is that VueJS prioritizes the v-for directive over the v-if directive. So under the hood, it loops through every element and THEN checks the v-if conditional.

Why does vuejs loop through an array before rendering?

The problem with this is that VueJS prioritizes the v-for directive over the v-if directive. So under the hood, it loops through every element and THEN checks the v-if conditional. This means that even if we only want to render a few elements from a list, we’ll have to loop through the entire array.

What is V-If loop in Vue JS?

This is when v-if comes in handy. It runs the loop only if a certain condition is true. Based on the Boolean value the UI response is set. This comes under the part of “ Vue JS Conditional Rendering “. <ul v-if="condition" > <li v-for="condition"> Content ....... <li> </ul>

How to display submitted text in column 2 in Vue?

A form is used to submit text and two options which tell vue which column to display the text in. When the col2 radio button is checked the submitted text should display in column 2. This is not happening, on column 1 text is displaying.


3 Answers

Why don't use the power of Computed Properties ?

computed: {
  infoOne: function () {
    return this.info.filter(i => i.col === 'one')
  },
  infoTwo: function () {
    return this.info.filter(i => i.col === 'two')
  }
}

Then on each list just iterate over its respective property without the need to check. Example

<ol>
   <li v-for="item in infoOne">{{item}}</li>
</ol>

Here the working fiddle

like image 79
DobleL Avatar answered Oct 16 '22 18:10

DobleL


<div class="row">
    <div class="col-md-6">
        <ol>
            <li v-for="item in info">
                <template v-if="item.col==='one'">
                    text: {{ item.text }}, col: {{ item.col }}
                <template>
            </li>
        </ol>
    </div>
    <div class="col-md-6">
        <ol>
            <li v-for="item in info">
                <template v-if="!item.col==='two'">
                    text: {{ item.text }}, col: {{ item.col }}
                <template>
            </li>
        </ol>
    </div>
</div>
like image 42
Agus Mathew Avatar answered Oct 16 '22 16:10

Agus Mathew


From Vue docs:

When they exist on the same node, v-if has a higher priority than v-for. That means the v-if condition will not have access to variables from the scope of the v-for:


<!--
This will throw an error because property "todo"
is not defined on instance.
-->
<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo.name }}
</li>

This can be fixed by moving v-for to a wrapping tag (which is also more explicit):

<template v-for="todo in todos">   
  <li v-if="!todo.isComplete">
     {{ todo.name }}   
  </li> 
</template> 

If you don't mind your view continuing in the html with "display:none" you can use v-show together with v-for without any problems.

like image 12
Mithsew Avatar answered Oct 16 '22 17:10

Mithsew