首页 > 解决方案 > 检查多个复选框时过滤数据

问题描述

目前在我的应用程序中,用户可以通过输入游戏名称来搜索游戏名称。当他们开始使用过滤器方法输入结果更新。我现在正在尝试使用多个复选框来做同样的事情。因此,当用户例如检查 playstation 和/或 xbox 时,结果仅显示这些类别的游戏。当他们取消选中时,结果将使用更新的值刷新。

目前我已经成功地为所有复选框创建了更改事件并将它们的值推送到 filters.categories 数组。我遇到的问题是我不知道如何将此数组连接到我现有的过滤器方法。我需要以某种方式遍历数组并将当前值与我的商店对象中的 category.name 进行比较,以查看它们是否匹配。这可以在过滤器方法中执行吗?有什么想法我哪里出错了吗?

提前致谢。

的HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <aside>
        <ul>
            <li>
                <label>
                    <input type="checkbox" value="playstation" class="category-cb">
                    <span>Playstation</span>
                </label>
                <li>
                    <label>
                        <input type="checkbox" value="xbox" class="category-cb">
                        <span>Xbox</span>
                    </label>
                </li>
                <li>
                    <label>
                        <input type="checkbox" value="nintendo" class="category-cb">
                        <span>Nintendo</span>
                    </label>
                </li>
            </li>
        </ul>
    </aside>
    <main>
        <input type="text" class="store-search" placeholder="Search">
        <ul class="grid"></ul>
    </main>

    <script src="app.js"></script>
</body>
</html>

js:

/*----------------------------
    data
----------------------------*/

const stores = [{
    id: 0,
    name: 'The Last Of Us',
    studio: 'Naughtydog',
    thumbnail: '',
    category: {
        id: 0,
        name: 'Playstation'
    },
    price: 50.00
}, {
    id: 1,
    name: 'Animal Crossing',
    studio: 'Nintendo',
    thumbnail: '',
    category: {
        id: 1,
        name: 'Nintendo'
    },
    price: 60.00
}, {
    id: 2,
    name: 'Gears 5',
    studio: 'The Coalition',
    thumbnail: '',
    category: {
        id: 2,
        name: 'Xbox'
    },
    price: 10.00
}, {
    id: 3,
    name: 'DOOM Eternal',
    studio: 'id Software',
    thumbnail: '',
    category: {
        id: 3,
        name: 'Playstation'
    },
    price: 50.00
}, {
    id: 4,
    name: 'The Legend of Zelda: Link\'s Awakening',
    studio: 'Grezzo',
    thumbnail: '',
    category: {
        id: 4,
        name: 'Nintendo'
    },
    price: 35.00
}, {
    id: 5,
    name: 'Resident Evil 3',
    studio: 'Capcom',
    thumbnail: '',
    category: {
        id: 5,
        name: 'Playstation'
    },
    price: 40.00
}];

let filters = {
    searchText: '',
    categories: []
}

/*----------------------------
    functions
----------------------------*/

let filterStores = function (stores, filters) {

    let filteredStores = stores.filter(function (store) {
        let storeName = store.name.toLowerCase().includes(filters.searchText.toLowerCase());
        return storeName;
    });

    let grid = document.querySelector('.grid');
    grid.innerHTML = '';

    filteredStores.forEach(function (store) {
        let li = document.createElement('li');
        li.textContent = store.name;
        grid.appendChild(li);
    });
}

/*----------------------------
    events
----------------------------*/

document.addEventListener('DOMContentLoaded', function () {
    filterStores(stores, filters);

    document.querySelector('.store-search').addEventListener('input', function (event) {
        filters.searchText = event.target.value;
        filterStores(stores, filters);
    });

    document.querySelectorAll('.category-cb').forEach(function (checkbox) {
        checkbox.addEventListener('change', function (event) {
            if (checkbox.checked) {
                filters.categories.push(event.target.value);
                filterStores(stores, filters);
                console.log(filters.categories);
            }
        });
    });
});

https://jsfiddle.net/bjgp0ux4/

标签: javascript

解决方案


要实现的主要功能有两个:

  1. 未选中时删除类别

    我建议您使用 Set as ,这样您就可以轻松地分别通过、和filters.categories来检查、添加和删除条目。hasadddelete

    //onchange event
    if (checkbox.checked) {
        filters.categories.add(event.target.value);
    } else {
        filters.categories.delete(event.target.value);
    }
    filterStores(stores, filters);
    
  2. 也过滤stores基于类别

    修改你的.filter回调也考虑到这一点:

    store.name.toLowerCase().includes(filters.searchText.toLowerCase()) &&
    filters.categories.has(store.category.name.toLowerCase())
    

    此外,要在未选择任何类别时显示全部,请执行以下操作:

    store.name.toLowerCase().includes(filters.searchText.toLowerCase()) &&
    (
        filters.categories.has(store.category.name.toLowerCase()) ||
        filters.categories.size === 0
    )
    

全部一起:

/*----------------------------
    data
----------------------------*/

const stores = [{
    id: 0,
    name: 'The Last Of Us',
    studio: 'Naughtydog',
    thumbnail: '',
    category: {
        id: 0,
        name: 'Playstation'
    },
    price: 50.00
}, {
    id: 1,
    name: 'Animal Crossing',
    studio: 'Nintendo',
    thumbnail: '',
    category: {
        id: 1,
        name: 'Nintendo'
    },
    price: 60.00
}, {
    id: 2,
    name: 'Gears 5',
    studio: 'The Coalition',
    thumbnail: '',
    category: {
        id: 2,
        name: 'Xbox'
    },
    price: 10.00
}, {
    id: 3,
    name: 'DOOM Eternal',
    studio: 'id Software',
    thumbnail: '',
    category: {
        id: 3,
        name: 'Playstation'
    },
    price: 50.00
}, {
    id: 4,
    name: 'The Legend of Zelda: Link\'s Awakening',
    studio: 'Grezzo',
    thumbnail: '',
    category: {
        id: 4,
        name: 'Nintendo'
    },
    price: 35.00
}, {
    id: 5,
    name: 'Resident Evil 3',
    studio: 'Capcom',
    thumbnail: '',
    category: {
        id: 5,
        name: 'Playstation'
    },
    price: 40.00
}];

let filters = {
    searchText: '',
    categories: new Set
}

/*----------------------------
    functions
----------------------------*/

let filterStores = function (stores, filters) {

    let filteredStores = stores.filter(store => (
        store.name.toLowerCase().includes(filters.searchText.toLowerCase()) &&
        (
            filters.categories.has(store.category.name.toLowerCase()) ||
            filters.categories.size === 0 //No selected categories, show all
        )
    ));

    let grid = document.querySelector('.grid');
    grid.innerHTML = '';

    filteredStores.forEach(function (store) {
        let li = document.createElement('li');
        li.textContent = store.name;
        grid.appendChild(li);
    });
}

/*----------------------------
    events
----------------------------*/

document.addEventListener('DOMContentLoaded', function () {
    filterStores(stores, filters);

    document.querySelector('.store-search').addEventListener('input', function (event) {
        filters.searchText = event.target.value;
        filterStores(stores, filters);
    });

    document.querySelectorAll('.category-cb').forEach(function (checkbox) {
        checkbox.addEventListener('change', function (event) {
            if (checkbox.checked) {
                filters.categories.add(event.target.value);
            } else {
                filters.categories.delete(event.target.value);
            }
            filterStores(stores, filters);
        });
    });
});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <aside>
        <ul>
            <li>
                <label>
                    <input type="checkbox" value="playstation" class="category-cb">
                    <span>Playstation</span>
                </label>
            </li>
            <li>
                <label>
                    <input type="checkbox" value="xbox" class="category-cb">
                    <span>Xbox</span>
                </label>
            </li>
            <li>
                <label>
                    <input type="checkbox" value="nintendo" class="category-cb">
                    <span>Nintendo</span>
                </label>
            </li>
        </ul>
    </aside>
    <main>
        <input type="text" class="store-search" placeholder="Search">
        <ul class="grid"></ul>
    </main>

    <script src="app.js"></script>
</body>
</html>

您还可以使用数组:

/*----------------------------
    data
----------------------------*/

const stores = [{
    id: 0,
    name: 'The Last Of Us',
    studio: 'Naughtydog',
    thumbnail: '',
    category: {
        id: 0,
        name: 'Playstation'
    },
    price: 50.00
}, {
    id: 1,
    name: 'Animal Crossing',
    studio: 'Nintendo',
    thumbnail: '',
    category: {
        id: 1,
        name: 'Nintendo'
    },
    price: 60.00
}, {
    id: 2,
    name: 'Gears 5',
    studio: 'The Coalition',
    thumbnail: '',
    category: {
        id: 2,
        name: 'Xbox'
    },
    price: 10.00
}, {
    id: 3,
    name: 'DOOM Eternal',
    studio: 'id Software',
    thumbnail: '',
    category: {
        id: 3,
        name: 'Playstation'
    },
    price: 50.00
}, {
    id: 4,
    name: 'The Legend of Zelda: Link\'s Awakening',
    studio: 'Grezzo',
    thumbnail: '',
    category: {
        id: 4,
        name: 'Nintendo'
    },
    price: 35.00
}, {
    id: 5,
    name: 'Resident Evil 3',
    studio: 'Capcom',
    thumbnail: '',
    category: {
        id: 5,
        name: 'Playstation'
    },
    price: 40.00
}];

let filters = {
    searchText: '',
    categories: []
}

/*----------------------------
    functions
----------------------------*/

let filterStores = function (stores, filters) {

    let filteredStores = stores.filter(store => (
        store.name.toLowerCase().includes(filters.searchText.toLowerCase()) &&
        (
            filters.categories.includes(store.category.name.toLowerCase()) ||
            filters.categories.length === 0 //No selected categories, show all
        )
    ));

    let grid = document.querySelector('.grid');
    grid.innerHTML = '';

    filteredStores.forEach(function (store) {
        let li = document.createElement('li');
        li.textContent = store.name;
        grid.appendChild(li);
    });
}

/*----------------------------
    events
----------------------------*/

document.addEventListener('DOMContentLoaded', function () {
    filterStores(stores, filters);

    document.querySelector('.store-search').addEventListener('input', function (event) {
        filters.searchText = event.target.value;
        filterStores(stores, filters);
    });

    document.querySelectorAll('.category-cb').forEach(function (checkbox) {
        checkbox.addEventListener('change', function (event) {
            if (checkbox.checked) {
                filters.categories.push(event.target.value);
            } else {
                filters.categories.splice(filters.categories.indexOf(event.target.value), 1);
            }
            filterStores(stores, filters);
        });
    });
});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <aside>
        <ul>
            <li>
                <label>
                    <input type="checkbox" value="playstation" class="category-cb">
                    <span>Playstation</span>
                </label>
            </li>
            <li>
                <label>
                    <input type="checkbox" value="xbox" class="category-cb">
                    <span>Xbox</span>
                </label>
            </li>
            <li>
                <label>
                    <input type="checkbox" value="nintendo" class="category-cb">
                    <span>Nintendo</span>
                </label>
            </li>
        </ul>
    </aside>
    <main>
        <input type="text" class="store-search" placeholder="Search">
        <ul class="grid"></ul>
    </main>

    <script src="app.js"></script>
</body>
</html>


推荐阅读