用于ng-repeat项目的角度多重过滤器

时间:2014-11-12 02:09:00

标签: angularjs

我有一个包含多个过滤器的ng-repeat列表。

    <div class="search pull-right">
        <div class="magnify"><img src="img/magnify.png" ng-click="magnify()"></div>
    </div>
    <div class="search-box" ng-show="showSearch">
        <input type="search" id="searchField" name="" value="" placeholder="Search" class="textfield" ng-model="search.firstName" /> 
    </div>

列表1(attendee.chat不为0)受搜索TextField影响

        <ul class="table-view">      
            <li class="table-view-cell attendee" ng-repeat="attendee in attendees | filter:search | filter:attendee.chat">
                <h2 class="name">{{attendee.firstName}} {{attendee.lastName}}</h2>
                <span class="job">{{attendee.title}}</span>
                <span class="company">{{attendee.company}}</span>
            </li>
        </ul>

列表2(attendee.chat为0)但也会受到搜索TextField

的影响
<ul class="table-view">      
                <li class="table-view-cell attendee" ng-repeat="attendee in attendees | filter:search | filter:attendee.chat">
                    <h2 class="name">{{attendee.firstName}} {{attendee.lastName}}</h2>
                    <span class="job">{{attendee.title}}</span>
                    <span class="company">{{attendee.company}}</span>
                </li>
            </ul>

任何DRY方法也会受到赞赏,因为我有两个类似的模板。 (差异是与会者。聊天可以是0或任何正数)

1 个答案:

答案 0 :(得分:1)

方法1

要使标记更干,您可以创建一个指令:

app.directive('attendeeDetails', function () {
    return {
        restrict: 'E',
        replace: true, // even though this option is deprecated
        scope: {
            attendee: '&' // don't need 2-way binding
        }
        template: '<li class="table-view-cell attendee">' +
            '<h2 class="name">{{attendee().firstName}} {{attendee().lastName}}</h2>' + 
            '<span class="job">{{attendee().title}}</span>' +
            '<span class="company">{{attendee().company}}</span>' +
        '</li>'
     };
 });

然后只需更改标记即可使用它:

清单1:

<ul class="table-view">      
     <attendee-details attendee="attendee" ng-repeat="attendee in attendees | filter:list1Filter"></attendee-details>
</ul>

清单2:

<ul class="table-view">      
     <attendee-details attendee="attendee" ng-repeat="attendee in attendees | filter:list2Filter"></attendee-details>
</ul>

然后在控制器中编写两个简单的过滤函数:

$scope.list1Filter = function (attendee) {
    return matchesSearch(attendee) && attendee.chat > 0;
};

$scope.list2Filter = function (attendee) {
    return matchesSearch(attendee) && attendee.chat === 0;
};

function matchesSearch(attendee) {
    return attendee.firstName.toLocaleLowerCase().indexOf($scope.search.firstName.toLocaleLowerCase()) >= 0;
}

(我使用的是.toLocaleLowerCase()而不是.toLowerCase(),因为这已成为我的偏好,因此它可以满足任何特定于语言环境的情况。如果我不得不将代码移植到土耳其工作,请省下我的努力例如。)

方法2

您也可以将模板与ng-include一起使用,如下所示:

<script type="text/ng-template" id="/attendee-details.html">
     <h2 class="name">{{attendee.firstName}} {{attendee.lastName}}</h2>
     <span class="job">{{attendee.title}}</span>
     <span class="company">{{attendee.company}}</span>
</script>

然后你的标记将变为如下:

清单1:

<ul class="table-view">      
     <li class="table-view-cell attendee" 
         ng-include="'/attendee-details.html'"
         ng-repeat="attendee in attendees | filter:list1Filter">
     </li>
</ul>

清单2:

<ul class="table-view">      
     <li class="table-view-cell attendee" 
         ng-include="'/attendee-details.html'"
         ng-repeat="attendee in attendees | filter:list2Filter">
     </li>
</ul>

请注意,这种方法的明显缺点是,如果要创建有效的HTML标记,则无法将<li>放在模板中,因为模板的内容将插入内部上面有ng-include的节点。由于有效的HTML除了<ul>以外的<li>内不能包含任何内容,因此您需要为这两个列表复制<li>及其类。

为什么不是多个过滤器?

我选择使用过滤器的控制器功能而不是在表达式中使用多个内联过滤器的原因是,显示所有带attendee.chat > 0的元素的列表1的条件无法使用任何据我所知,内置过滤器的内容。您无法为要匹配的事物指定表达式。

可以对列表2使用多个过滤器,因为你只检查attendee.chat(0)的单个值。

您可以执行ng-repeat="attendee in attendees | filter:{firstName:search.firstName,chat:0}",或者如果您必须使用多个过滤器(这会更慢,所以我不知道您为什么会这样做),您可以执行ng-repeat="attendee in attendees | filter:search | filter:{chat:0}"