Eloise85
Eloise85

Reputation: 676

Using method function in v-if

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

Upvotes: 12

Views: 58095

Answers (4)

linuxdan
linuxdan

Reputation: 4864

The simple answer is to use computed properties you won't be able to pass parameters to the computed property, but you can interact with the state of your component.

Upvotes: 0

Alexis Gatuingt
Alexis Gatuingt

Reputation: 547

If your method returns a boolean you can use

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

simple and clean

Upvotes: 0

Eloise85
Eloise85

Reputation: 676

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>

Upvotes: 1

paweloque
paweloque

Reputation: 18864

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>

Upvotes: 6

Related Questions