4

I have a Tagging Tool Component with 3 different levels of priority. Now I would like to a filter search. Is it possible to access tags[n] in the computed tagsFilter function?

This my current version: https://jsfiddle.net/hej7L1jy/26/

I would like to replace v-for="tag in tags[n]" with: v-for="tag in tagsFilter" In the moment I receive a TypeError: this.tags.filter is not a function

Does anyone have an idea?

Vue.js Template:

<div id="app">
  <input id="input-search" type="text" class="form-inline pull-right" v-model="textSearch" placeholder='Search...'>
  <div v-for="n in prios">
  <h3>{{n}} tag priority</h3>
    <ul v-if="tagsFilter && tagsFilter.length">
      <li :class="'tagPriority-'+n" v-for="tag in tagsFilter">
        <label class="checkbox-inline"><input name="tags[]" type="checkbox" v-model="tagSelected" :value="tag.id"> {{tag.title}}</label>
      </li>
    </ul>
  </div>
</div>

Vue.js component:

new Vue({
    el: '#app',
        props: {
            selectedTags: {
                type: Array
            }
        },
        data() {
            return {
                prios: [ 1, 2, 3 ],
                tagSelected: [],
                tags: [],
                textSearch: ''
            }
        },
        computed: {
            tagsFilter: function() {
                var textSearch = this.textSearch;
                return this.tags.filter(function(el) {
                    return el.title.toLowerCase().indexOf(textSearch.toLowerCase()) !== -1;
                });
            }
        },
        created: function () {
            this.tagSelected = this.selectedTags;
            this.tags = {"1":[{"id":9,"title":"Auto"}],"2":[{"id":8,"title":"Elektroauto"}],"3":[{"id":10,"title":"BMW i3"},{"id":11,"title":"Opel Ampera"},{"id":12,"title":"Renault TWIZY"}]};       
        }

});

1 Answer 1

4

Although you define tags in your data:

data() {
    return {
        tags: [],
    }
},

Your created callback overrides this.tags:

created: function () {
    this.tagSelected = this.selectedTags;
    this.tags = {"1":[{"id":9,"title":"Auto"}],"2":[{"id":8,"title":"Elektroauto"}],"3":[{"id":10,"title":"BMW i3"},{"id":11,"title":"Opel Ampera"},{"id":12,"title":"Renault TWIZY"}]};       
}

Turning it into an object, which has no filter method.

Filtering using a computed property

Your template:

<li :class="'tagPriority-'+n" v-for="tag in tags[0]">

Becomes

<li :class="'tagPriority-'+n" v-for="tag in tagsFilter[n]">

And

computed: {
    tagsFilter: function() {
        var textSearch = this.textSearch;
        return this.tags.filter(function(el) {
            return el.title.toLowerCase().indexOf(textSearch.toLowerCase()) !== -1;
        });
    }
},

Becomes:

computed: {
    tagsFilter: function() {
        var textSearch = this.textSearch;
        var filteredTags = {};
        var tags = this.tags;
        Object.keys(this.tags).forEach(function(key) {
            filteredTags[key] = tags[key].filter(function(el) {
                return el.title.toLowerCase().indexOf(textSearch.toLowerCase()) !== -1;
            });
        });
        return filteredTags;
    },
},

Basically, we are iterating each of this.tags properties and adding a filtered version of each of them to filteredTags.

Demo JSFiddle here.



Filtering using a method

Another way (least amount of changed code) is to change your computed into a method with an argument:

<li :class="'tagPriority-'+n" v-for="tag in tags[0]">

Becomes

<li :class="'tagPriority-'+n" v-for="tag in tagsFilter(n)">

And

computed: {
    tagsFilter: function() {
        var textSearch = this.textSearch;
        return this.tags.filter(function(el) {
            return el.title.toLowerCase().indexOf(textSearch.toLowerCase()) !== -1;
        });
    }
},

Becomes:

methods: {
    tagsFilter: function(i) {
        var textSearch = this.textSearch;
        return this.tags[i].filter(function(el) {
            return el.title.toLowerCase().indexOf(textSearch.toLowerCase()) !== -1;
        });
    },
},

Demo JSFiddle here.

Sign up to request clarification or add additional context in comments.

3 Comments

Yeah my component is a little bigger... I changed my example fiddle: jsfiddle.net/hej7L1jy/32
@hasentopf Okay! I added two possible solutions. They work for both versions of your fiddles.
Thank you @acdcjunior ! The computed property solution works perfect, because the tags come via Axios.get()

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.