简体   繁体   中英

Create multiple dynamic select filters based on an array with unique values to filter another array in Vue.js

I am currently new to Vue.js and this is my first question on stack so forgive me if I am not the most clear.

I am trying to create multiple dynamic select filters to filter a list that I have gotten from an api using axios.

I have surfaced the data within my HTML template and have managed to create the two filters, my main issue is that I need the filters to only display unique values (no duplicates) and this is where I am struggling.

This is mainly a proof of concept for work which displays a group of users names, there label and position. We where using angularjs before and are now looking to move over to Vue.js, so I haven't gotten to grips with it yet, and currently stumped as I don't understand how to make the information from one source data array filter another source data array.

Here is what I have currently in my app.js

new Vue({
        el: "#vueApp",        
        data: {
            users: [],
            JobRole: '',
            Label: '',
            search: '',
            JobRoles: [],
        },
        created: function() {
            this.getResults();
        },


        methods: {
            getResults: function() {
                var vm = this;
                axios.get("APIData").then(function(response) {
                    console.log(response.data.value);
                    vm.users = response.data.value;
                })
            },

            filterPosition:function() {
                var vm = this;
                vm.item.Position = event.target.value;
            },

            filterLabel:function() {
                var vm = this;
                vm.item.Meta.Label = event.target.value;
            }

        },

        computed: {

            JobRoleList: function(){
                var vm = this;
                var JobRoles = [];
                vm.users.forEach(function(item){
                    if(!JobRoles.includes(item.Position)){
                        JobRoles.push(item.Position);  
                        console.log(JobRoles);                          
                    }

                });

                return JobRoles;

            },

                filterAll: function(){
                    var vm = this;
                    var filtered = vm.users;
                    // var JobRoles = vm.JobRoles;

                    if (vm.search) {
                        filtered = vm.users.filter(function(item){
                            return item.People.Title.indexOf(vm.search) > -1
                        });
                    }

                    if (vm.Label) {
                        filtered = filtered.filter(function(item){
                            return item.Meta.Label.match(vm.Label)
                        });
                    }

                    if (vm.JobRole) {
                        vm.JobRole = filtered.filter(function(item){
                            return item.Position.match(vm.JobRole)
                            console.log(JobRole);
                        });
                    }

                    return filtered
                    console.log(filtered);
                },

}




});

Here is my Markup

<div id="vueApp">
    <div>
        <select v-model="JobRole">
            <option value="">Select a Position</option>
            <option v-for="item in JobRoleList" :value="item.Position">{{item}}</option>
        </select>

        <select v-model="Label">
            <option value="">Select a Label</option>
            <option v-for="item in filterAll" :value="item.Meta.Label">{{item.Meta.Label}}</option>
        </select>

        <input type="text" v-model="search" placeholder="Search...">

        <table>
            <tr>
                <th>Name</th>
                <th>Department</th>
                <th>Position</th>
                <!-- <th>People Title</th> -->
            </tr>
            <tr v-for="item in filterAll">
                <td>{{item.People.Title}}</td>
                <td>{{item.Meta.Label}}</td>
                <td>{{item.Position}}</td>

            </tr>
        </table>
    </div>
</div>

So what I want to get to is have each filter to have unique values with no duplication and to filter the information within the list.

I have managed to create a unique value array for one of the select filters under JobRoleList, I just need to know how to have it communicate with the filterAll array, if I can get to that stage then all I would need to do is replicate that for the other filter.

I would appreciate any help and would be more than happy to provide more detail.

There are a few problems with your code:

  1. You're binding the wrong value to the job role select. Right now your code says :value="item.Position" when the JobRoleList variable is an array of strings. So when you click select there won't be a value for JobRole
        <select v-model="JobRole">
            <option value="">Select a Position</option>
            <option v-for="item in JobRoleList" :value="item.Position">{{item}}</option>
        </select>
  1. You're filtering the wrong variable in your filterAll computed variable in the jobRole part
    if (vm.JobRole) {
        vm.JobRole = filtered.filter(function(item){
            return item.Position.match(vm.JobRole)
            console.log(JobRole);
        });
        // This should say "filtered =" not "vm.JobRole ="
    }

There's also a much more succinct way to get a unique list of values using ES6:

    JobRoleList: function({ users }) {
      return [...new Set(users.map(d => d.Position))];
    }

You can also make your search all lower case letters before matching to improve the user experience.

        filtered = users.filter(function(item){
          return item.People.Title.toLowerCase().indexOf(search.toLowerCase()) > -1
        });

I've made a codepen with a working demo: https://codepen.io/CodingDeer/pen/abomBXP

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM