1

在 AngularJS 中,我有一个 ng-repeat 元素和一个搜索框。

我可以在 ng-repeat 上使用过滤器来根据搜索条件显示/隐藏元素。

如何根据搜索条件将 CSS 类应用于元素?- 即使所有符合搜索条件的元素变为蓝色。

4

3 回答 3

2

使用ng-class有条件地申请课程怎么样?

<input ng-model="search" type="text" />
<ul>
    <li ng-repeat="item in items" ng-class="{'found': find(item.text, search)}">{{item.text}}</li>
</ul>

然后在您的控制器中,如下所示:

$scope.find = function(text, search) {
    if(!text || !search) return false;
    return text.toLowerCase().indexOf(search.toLowerCase()) >= 0;
};

这是一个有效的 CodePen

如果你更喜欢使用现有的filter实现,你可以把它拉出来使用:

function TestCtrl($scope, $filter) {
    var filterFilter = $filter('filter');

    $scope.findViaFilter = function(text, search) {
        if(!text || !search) return false;
        return filterFilter([text], search).length > 0;
    };
}
于 2013-09-05T01:45:50.337 回答
0

如果我理解正确,您希望使用与内置过滤器过滤器相同的功能(有史以来最糟糕的名称),而不是删除未通过过滤器的项目,您只想突出显示通过过滤器的项目。

实际值检查功能没有暴露,但很容易从源头中提取;这是filterFilter实施。您将使用它来创建包装predicate.check函数的单值过滤器。这部分相当简单,现在您可以对单个值运行默认过滤器功能。

app.filter('singleValueFilter', [function() {
  return function(valueToCheck, expression, comperator) {
    var predicates = [];
    predicates.check = function(value) {
      for (var j = 0; j < predicates.length; j++) {
        if(!predicates[j](value)) {
          return false;
        }
      }
      return predicates.length > 0;
    };
    switch(typeof comperator) {
      case "function":
        break;
      case "boolean":
        if(comperator == true) {
          comperator = function(obj, text) {
            return angular.equals(obj, text);
          };
          break;
        }
      default:
        comperator = function(obj, text) {
          text = (''+text).toLowerCase();
          return (''+obj).toLowerCase().indexOf(text) > -1;
        };
    }
    var search = function(obj, text){
      if (typeof text == 'string' && text.charAt(0) === '!') {
        return !search(obj, text.substr(1));
      }
      switch (typeof obj) {
        case "boolean":
        case "number":
        case "string":
          return comperator(obj, text);
        case "object":
          switch (typeof text) {
            case "object":
              return comperator(obj, text);
            default:
              for ( var objKey in obj) {
                if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
                  return true;
                }
              }
              break;
          }
          return false;
        case "array":
          for ( var i = 0; i < obj.length; i++) {
            if (search(obj[i], text)) {
              return true;
            }
          }
          return false;
        default:
          return false;
      }
    };
    switch (typeof expression) {
      case "boolean":
      case "number":
      case "string":
        expression = {$:expression};
      case "object":
        for (var key in expression) {
          if (key == '$') {
            (function() {
              if (!expression[key]) return;
              var path = key;
              predicates.push(function(value) {
                return search(value, expression[path]);
              });
            })();
          } else {
            (function() {
              if (!expression[key]) return;
              var path = key;
              predicates.push(function(value) {
                return search(getter(value,path), expression[path]);
              });
            })();
          }
        }
        break;
      case 'function':
        predicates.push(expression);
        break;
      default:
        return false;
    }
    return predicates.check(valueToCheck);
  };
}]);

[注意:如果您要最小化此功能,您可能必须包含该getter功能]

现在是困难的部分。您想根据列表项是否匹配来突出显示它。正如其他答案所指出的那样,在元素上设置一个类是解决此问题的最佳方法,但是它比看起来要复杂得多。

为了动态更新选定的属性,ng-class必须引用范围的属性,而不仅仅是尝试使用编译值。即类似的东西:

<span ng-class="{ 'selected': {{ listItem | singleValueFilter:filterTerm }} }">{{ listItem.name }}</span>

不会工作,因为它实际上会渲染一个在编译后不引用范围的模板:

<span ng-class="{ 'selected': false }">{{ listItem.name }}</span>

您实际上可以通过查看开发人员工具中的 dom 来验证这一点。即使过滤器的结果发生变化,它也会将 dom 更改为显示 selected 为 true,但由于它不引用范围,因此应用步骤不会触发更新。

此时您需要将 listItem 类选择器指向范围的一个属性,接下来需要解决的问题是如何将范围的属性设置为视图中指定的过滤器的结果。很抱歉,我没有答案,但希望这将为您提供足够的信息来缩小问题的范围。

于 2013-09-05T05:16:44.683 回答
0

这是一个工作小提琴

http://jsfiddle.net/zA7QN/52/

<div ng-controller="BabeController">
    <input ng-model="filter" />
<ul  >
    <li ng-repeat="babe in babeList">
            <span ng-class="{true: 'babe-hot', false:'babe-name'}[(filter == babe)]">{{babe}}</span>

    </li>
</ul>
</div>


.babe-name { color: blue;}
.babe-hot { color:red }


function BabeController($scope) {
    $scope.filter = '';
    $scope.babeList = [ 'angelina','scarlett','mila','megan'];
}
于 2013-09-05T02:14:03.673 回答