Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using method function in v-if

Tags:

vue.js

vuejs2

I’m trying to use a function in a v-if directive like that in a vue template

    <template>

    <ul class="list-group">
        <li class="list-group-item list-group-item-info">
            <div class="row">
                <div v-for="col in colss" class="" :class="bootstrapClass">{{col | capitalize}}</div>
            </div>
        </li>

        <li v-for="item in datas[collectionsindatas['reference']]" class="list-group-item">
            <div class="row">
                <div v-for="property in columns.slice(0,(columns.length))" class="" :class="bootstrapClass">{{ item[property] }}</div>

                <div v-if="compareCollections(item[comparecol],datas[collectionsindatas['compare'][comparecol]])" class="" :class="bootstrapClass">
                    OK
                </div>
                <div v-else class="" :class="bootstrapClass">!!NOK!!</div>

            </div>

        </li>
    </ul>

</template>

and my methods are like that :

methods:{
compareCollections:function(reference,compare){
                if(compare!='undefined'  && compare!=''){
                    if(compare===reference){
                        return true;
                    }
                    return false;
                }
                return false;
            },
}

It fails with this message : [Vue warn]: Property or method is not defined on the instance but referenced during render

It fells myself better to use a method instead writing many things ugly in the v-if directive like

v-if="datas[collectionsindatas['compare'][comparecol]]!='undefined'&&(item[comparecol]===datas[collectionsindatas['compare'][comparecol]])"

what is the right way to do this ?

Thanks for your help

like image 868
Eloise85 Avatar asked Jan 27 '18 19:01

Eloise85


People also ask

Can I use || with V-if?

You can pass an arbitrary JavaScript expression to the v-if directive in Vue, including a complex boolean expression which contains operators || or && . You can test this on your own.

How do you write if condition in Vue?

v-else-if directive is a Vue. js directive used to toggle the display CSS property of an element depending on a condition when the if condition is not satisfied. First, we will create a div element with id as app and let's apply the v-else-if directive to an element with data.

How does v-If work?

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 is Vshow?

The v-show directive is a Vue. js directive used to toggle the display CSS property of a element with our data via inline styles. If the data is true it will make it visible else it will make it invisible.


3 Answers

In order to get rid of this comparison in your v-if I'd use a component with your parameters. In the component you can calculate the values and provide them using computed. You won't have to pass any parameters to computed because they will already be the parameters of the component:

<template>
  <div>
    <div v-if="compEqRef" class="" :class="bootstrapClass">
      OK
    </div>
    <div v-else class="" :class="bootstrapClass">!!NOK!!</div>
  </div>
</template>

<script>
  export default {

    methods: {
      compareCollections(reference, compare) {
        return (compare !== 'undefined' && compare !== '' && compare === reference);
      }
    },

    computed: {
      compEqRef() {
        const left = this.item[this.comparecol];
        const right = this.datas[this.collectionsindatas['compare'][this.comparecol]];

        return this.compareCollections(left, right);
      }
    },

    props: {
      item: {
        required: true
      },
      datas: {
        required: true
      },
      comparecol: {
        required: true
      },
      collectionsindatas: {
        required: true
      }
    }
  }
</script>
like image 100
paweloque Avatar answered Oct 17 '22 02:10

paweloque


OK, it could be improved but here is my way to resolve this :

My list component receive by props a reference list of avalaible permissions and receive a comparing list to the role's permission so when the comparing returns true it will display a toggle switch wich appear set on ON position and OFF if it's false. So here is the app.js :

Vue.component('sort-table', sortTable);
Vue.component('list-items', listItems);

var csrf_token = $('meta[name="csrf-token"]').attr('content');

var newTable = new Vue({
    el: '#appTableRoles',
    data: {

        columns: ['id', 'name', 'description', 'action'],
        cols: ['Id', 'Rôle', 'Description', 'Actions'],
        // ajax url
        url: 'Role/ajaxQuery',

    },
    components: {sortTable},

});

var listTable = new Vue({
    el: '#listmodal',
    data: {
        // collection des propriétés
        columns: ['id', 'name', 'description'],
        // collection d'affichage
        colss: ['Id', 'Nom', 'Description', 'Attribution'],
        urlajax:'',
        datas:[],
        //
        collectionsInDatas:{'reference':'allPermissions','compare':'rolePermissions'},
        // critère de comparaison entre la collection de référence et la collection appartenant à l'item
        comparecol:'name',
        //objet contenant tous les résultats de comparaisons
        lastcol:{equal:[],display:[]},

    },
    methods: {
        showModal () {
            $('#permissionsModal').modal('show');
        },
        hideModal () {
            $('#permissionsModal').modal('hide');
        },

        getDatas(){

            this.lastcol.equal =[];
            this.lastcol.display =[];

            MonThis = this;
            $.ajax({
                url: this.urlajax,
                cache: false,
                dataType: 'json',
                success: function (data, textStatus, jqXHR) {
                    if (jqXHR.status === 200) {
                        //console.log(data);
                        MonThis.datas = data;
                        var index=0;
                        //console.log(MonThis.datas[MonThis.collectionsInDatas['reference']]);
                        for(item in MonThis.datas[MonThis.collectionsInDatas['reference']]){

                            //var index = MonThis.datas[MonThis.collectionsInDatas['reference']].indexOf(item);
                            //console.log('index : '+index);

                            console.log('reference name : '+MonThis.datas[MonThis.collectionsInDatas['reference']][index]['name']);
                            //console.log('compare : '+MonThis.datas[MonThis.collectionsInDatas['compare']][index]);

                            var j = 0;
                            for(compare in MonThis.datas[MonThis.collectionsInDatas['compare']]){

                                //console.log('compare name : '+MonThis.datas[MonThis.collectionsInDatas['compare']][j]['name']);

                                if(MonThis.datas[MonThis.collectionsInDatas['compare']][j]['name']===MonThis.datas[MonThis.collectionsInDatas['reference']][index]['name']){
                                    MonThis.lastcol.equal.push(true);
                                    MonThis.lastcol.display.push('OK');
                                    break;
                                }else{
                                    MonThis.lastcol.equal.push(false);
                                    MonThis.lastcol.display.push('Not OK');
                                }
                                j++;

                            }

                            index++;
                        }
                    }
                }
            });
        },


    },
    components:{listItems},

});

$(document).ready(function () {

    $(document).on('click', '.modal-permissions', function (e) {
        //console.log($(e.target).attr('href'));
        listTable.showModal();
        listTable.$data.urlajax = $(e.target).attr('href');
        listTable.getDatas();

    });

});

Here is the component call in the blade template :

<list-items :colss="colss":columns="columns"
            :urlajax="urlajax"
            :datas="datas"
            :lastcol="lastcol"
            :collectiondatas="collectionsInDatas">
</list-items>

and Here is the vue file code :

    <template>

    <ul class="list-group">
        <li class="list-group-item list-group-item-info">
            <div class="row">
                <div v-for="col in colss" class="" :class="bootstrapClass">{{col | capitalize}}</div>
            </div>
        </li>

        <li v-for="(item,index ) in datas[collectiondatas['reference']]" class="list-group-item">
            <div class="row">
                <div v-for="property in columns.slice(0,(columns.length))" class="" :class="bootstrapClass">{{
                    item[property] }}</div>


                <div class="" :class="bootstrapClass">{{ lastcol.display[index] }}</div>

            </div>

        </li>
    </ul>

</template>

<script>

    var csrf_token = $('meta[name="csrf-token"]').attr('content');

    export default {

        name: 'listItems',

        data(){
            return {


            }
        },

        props: ['colss','columns','lastcol','urlajax','datas','collectiondatas'],

        methods: {



        },

        computed: {
            bootstrapClass: function() {
                return 'col-sm-' + (12 / this.colss.length );
            },


        },

        mounted: function () {


        },

        filters: {

            capitalize: function (str) {
                return str.charAt(0).toUpperCase() + str.slice(1)
            }

        },

    }
</script>
like image 20
Eloise85 Avatar answered Oct 17 '22 03:10

Eloise85


If your method returns a boolean you can use

v-if="!!compareCollections(params)"

simple and clean

like image 1
Alexis Gatuingt Avatar answered Oct 17 '22 01:10

Alexis Gatuingt