AngularJS带搜索功能的多选组件问题求助(附自有代码)
Hey there! Let's fix those two issues in your AngularJS multi-select component step by step. I’ll stick close to your original code so it’s easy for you to follow along.
Issue 1: Searching for "a" doesn't filter correctly
The root cause here is twofold:
- Your checkbox was incorrectly bound to
selectedItems(an array) instead of theflagproperty of each data item, which messed up state tracking. - The default AngularJS filter checks all properties of your data objects (including
flag: false), which could lead to unexpected matches. We’ll restrict the filter to only search theitemfield for accuracy.
Issue 2: Can't remove the last two items when unchecking in order
Your original code used the index of the data object in the unfiltered datas array to splice the selectedItems array. But when you apply a filter, the position of items in the displayed list doesn’t match their original index in datas. Additionally, selectedItems stores strings (like "a") while you were trying to search for an object in it, which would always return -1. We’ll fix this by targeting the actual item string in selectedItems.
Modified Full Code
JS Code
var app = angular.module("myApp", []); app.controller("myCtrl", function ($scope, $http) { $scope.selectEnable = false; $scope.selectedItems = []; $scope.openSelect = function () { $scope.selectEnable = !$scope.selectEnable; }; $scope.itemChecked = function (data) { data.flag = !data.flag; // Find the index of the item string in selectedItems var itemIndex = $scope.selectedItems.indexOf(data.item); if (data.flag) { // Add the item only if it's not already in the array if (itemIndex === -1) { $scope.selectedItems.push(data.item); } } else { // Remove the item only if it exists in the array if (itemIndex !== -1) { $scope.selectedItems.splice(itemIndex, 1); } } }; $scope.datas = [ { "item": "a", /*"category": "x",*/ "flag": false }, { "item": "b", /*"category": "y",*/ "flag": false }, { "item": "c", /*"category": "x",*/ "flag": false }, { "item": "d", /*"category": "y",*/ "flag": false } ]; });
CSS Code (no changes needed, included for completeness)
ul li { list-style: none; text-align: center; } #category { text-align: center; background: #ddd; } #listContainer { width: 20%; } span { cursor: pointer; }
HTML Code
<!DOCTYPE html> <html lang="en" ng-app="myApp"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script> <link rel="stylesheet" href="stylesheet/style.css"> </head> <body ng-controller="myCtrl"> <input type="text" ng-click="openSelect()"> <div id="selectContainer" ng-show="selectEnable"> <div>{{selectedItems.toString()}}</div> <input type="text" id="searchField" ng-model="searchField"> <div id="listContainer"> <ul> <!-- Restrict filter to only the "item" property, fix checkbox ng-model --> <li ng-repeat="data in datas | filter: {item: searchField}"> <input type="checkbox" ng-change="itemChecked(data)" name="select" ng-model="data.flag"> {{data.item}} </li> </ul> </div> </div> <script src="script.js"></script> </body> </html>
Key Changes Explained
- Checkbox ng-model: Changed from
selectedItemstodata.flagso the checkbox state correctly reflects the item's built-inflagproperty, fixing state consistency. - Filter refinement: Updated
filter: searchFieldtofilter: {item: searchField}so searches only target theitemtext, eliminating unintended matches from other properties. - Item removal logic: Instead of using the original array index, we now find the index of the actual item string (like "a") in
selectedItemsbefore splicing. This ensures we remove the correct entry regardless of filtering or selection order.
Now you should be able to:
- Search for "a" (or any character) and see only matching items
- Select/unselect items in any order without issues removing entries
内容的提问来源于stack exchange,提问作者mssoheil

