如何在 ng-repeat 中按 orderby 或其他过滤条件有条件地过滤?
How to conditionally filter by orderby or another filter criteria in an ng-repeat?
TLDR:我想要实现的目标: 如果存在 office.vote(如果存在),则按 office.vote 过滤。 candidateId.否则,按 office.candiateProfiles.vScore
排序
.offices(ng-repeat='office in service.offices' ng-class="{'last':$last}")
.row.row-format.text-uppercase
.office.ballot(ng-click='showCandidates = !showCandidates')
.col-xs-7.col-sm-4.col-md-4.mainBallot-col
.office-name
{{office.name}}
.col-xs-5.col-sm-8.col-md-8.border-left.mainBallot-col
.ballot(ng-repeat="candidate in office.candidateProfiles | orderBy: '-vScore' | filter: office.vote.candidateId | limitTo: 1 | " )
.row.noPad
.col-xs-1.col-sm-1.col-md-1.straight-col.ballotCheck-col
.col-xs-7.col-sm-7.col-md-7.straight-col.highest-col
%table.highestShow
%tr
%td
.vs
{{candidate.fullName}}
我意识到我尝试结合上面的 orderby 和 filter 是行不通的。我对自定义过滤器不是很熟悉。我怎样才能实现我想用自定义过滤器做的事情?
我认为我的问题是 candiateProfiles 是一个数组。
这是范围内的对象:
失败的尝试 2:
.ballot(ng-repeat="candidate in office.candidateProfiles | filter:criteriaMatch(office) | limitTo:1" )
控制器:
$scope.criteriaMatch = function(office) {
console.log(office);
if (office.vote) {
return office.vote.candidateId;
} else {
return orderBy(office.candidateProfiles.vScore)
}
};
在上面的控制器中,这适用于按 office.vote 过滤,但我需要一种新方法让 'else' 按最高 vScore 过滤。我认为它不能识别 candiateProfiles,因为它是一个数组。
好的。在澄清之后让我们试一试。看到这个 working Plnkr
我正在使用两种不同的 ng-repeats 来匹配一种或另一种情况。
案例 1 "No Vote set":
<!-- in case there is no vote -->
<div ng-if="main.office.vote == null">
No Vote set, show all candidates, orderedBy '-vScore'
<div ng-repeat="candidate in main.office.candidateProfiles | orderBy:'-vScore'">
{{candidate.fullName}}
</div>
</div>
案例二:"Vote set"
<!-- in case there is a vote -->
<div ng-if="main.office.vote != null">
Vote set: only show candidates matching the office, orderedBy '-vScore'
<div ng-repeat="candidate in main.office.candidateProfiles | filter:main.isOfficeIdMatching | orderBy:'-vScore'">
{{candidate.fullName}}
</div>
</div>
过滤发生在一个小函数内:
vm.isOfficeIdMatching = function(candidate) {
return vm.office.vote.officeId == candidate.officeId;
}
希望这就是您一直在寻找的。一般来说,如果你能用最少的数据准备一个小的 plnkr(就像我做的那样)来更好地理解你的问题,那就太好了。
总的来说,我想它可以进一步简化为只有一个 ng-repeat 并有一个过滤器函数,首先检查是否设置了投票,如果 - 它也调用 isOfficeIdMatching
函数.
编辑:
要检查这两种情况的结果,请删除 JSON 对象中的投票对象。
参见 app.js
中的 LoC 36-38
//remove the vote object, to see another output.
vote: {
officeId: 8
}
编辑 2:
要获得简化的解决方案:Simplified Plnkr(由于 OP 的评论,没有 ng-if)
没有 ng-if 了。 isVoteSet
函数负责检查 officeId 是否匹配。如果没有设置投票,它只是 returns true。
<div ng-repeat="candidate in main.office.candidateProfiles | filter:main.isVoteSet | orderBy:'-vScore'">
{{candidate.fullName}}
</div>
新的父函数:
vm.isVoteSet = function(candidate) {
if(vm.office.vote != null) {
return vm.isOfficeIdMatching(candidate);
}
return true;
}
编辑 3:
因为您的用例如下。
A) 如果设置了投票,过滤所有 candidateProfiles 以匹配已投票的人
B) 如果没有设置投票,就按vScore排序列表
这里是您问题的最终解决方案:Final Plnkr
HTML
<div ng-repeat="candidate in main.office.candidateProfiles| filter:main.isVoteSet | orderBy:main.whichOrderByPredicate">
<label>
<input type="checkbox" ng-click="main.setVote(candidate)"/>
{{candidate.fullName}}
</label>
</div>
JS
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var vm = this;
vm.office = {
name: "Metro Mayer",
candidateProfiles: [
{
candidateId: 5,
fullName: "John (Id 15, Score 1)",
vScore: 1
},
{
candidateId: 8,
fullName: "Linda (Id 8, Score 3)",
vScore: 3
},
{
candidateId: 120,
fullName: "Ben (Id 120, Score 2)",
vScore: 2
},
{
candidateId: 14,
fullName: "Rick (Id 14, Score 1)",
vScore: 1
},
{
candidateId: 15,
fullName: "Tesla (Id 15, Score 2)",
vScore: 2
}
],
vote: {}
};
/*Filtering functions
only used if a vote is set
*/
vm.isVoteSet = function(candidate) {
if(JSON.stringify(vm.office.vote) != "{}") {
return vm.isCandidateIdMatching(candidate);
}
return true;
};
vm.isCandidateIdMatching = function(candidate) {
return vm.office.vote.candidateId == candidate.candidateId;
};
/*Ordering functions
only used if NO vote is set
*/
vm.whichOrderByPredicate = function(candidate) {
return JSON.stringify(vm.office.vote) == "{}" ? -candidate.vScore : null;
};
/* Application logic */
vm.setVote = function(candidate) {
//unset if already set
if(vm.office.vote.candidateId == candidate.candidateId) {
vm.office.vote = {};
}
//else set the vote
else {
vm.office.vote.candidateId = candidate.candidateId
}
};
});
TLDR:我想要实现的目标: 如果存在 office.vote(如果存在),则按 office.vote 过滤。 candidateId.否则,按 office.candiateProfiles.vScore
排序.offices(ng-repeat='office in service.offices' ng-class="{'last':$last}")
.row.row-format.text-uppercase
.office.ballot(ng-click='showCandidates = !showCandidates')
.col-xs-7.col-sm-4.col-md-4.mainBallot-col
.office-name
{{office.name}}
.col-xs-5.col-sm-8.col-md-8.border-left.mainBallot-col
.ballot(ng-repeat="candidate in office.candidateProfiles | orderBy: '-vScore' | filter: office.vote.candidateId | limitTo: 1 | " )
.row.noPad
.col-xs-1.col-sm-1.col-md-1.straight-col.ballotCheck-col
.col-xs-7.col-sm-7.col-md-7.straight-col.highest-col
%table.highestShow
%tr
%td
.vs
{{candidate.fullName}}
我意识到我尝试结合上面的 orderby 和 filter 是行不通的。我对自定义过滤器不是很熟悉。我怎样才能实现我想用自定义过滤器做的事情?
我认为我的问题是 candiateProfiles 是一个数组。
这是范围内的对象:
失败的尝试 2:
.ballot(ng-repeat="candidate in office.candidateProfiles | filter:criteriaMatch(office) | limitTo:1" )
控制器:
$scope.criteriaMatch = function(office) {
console.log(office);
if (office.vote) {
return office.vote.candidateId;
} else {
return orderBy(office.candidateProfiles.vScore)
}
};
在上面的控制器中,这适用于按 office.vote 过滤,但我需要一种新方法让 'else' 按最高 vScore 过滤。我认为它不能识别 candiateProfiles,因为它是一个数组。
好的。在澄清之后让我们试一试。看到这个 working Plnkr
我正在使用两种不同的 ng-repeats 来匹配一种或另一种情况。
案例 1 "No Vote set":
<!-- in case there is no vote -->
<div ng-if="main.office.vote == null">
No Vote set, show all candidates, orderedBy '-vScore'
<div ng-repeat="candidate in main.office.candidateProfiles | orderBy:'-vScore'">
{{candidate.fullName}}
</div>
</div>
案例二:"Vote set"
<!-- in case there is a vote -->
<div ng-if="main.office.vote != null">
Vote set: only show candidates matching the office, orderedBy '-vScore'
<div ng-repeat="candidate in main.office.candidateProfiles | filter:main.isOfficeIdMatching | orderBy:'-vScore'">
{{candidate.fullName}}
</div>
</div>
过滤发生在一个小函数内:
vm.isOfficeIdMatching = function(candidate) {
return vm.office.vote.officeId == candidate.officeId;
}
希望这就是您一直在寻找的。一般来说,如果你能用最少的数据准备一个小的 plnkr(就像我做的那样)来更好地理解你的问题,那就太好了。
总的来说,我想它可以进一步简化为只有一个 ng-repeat 并有一个过滤器函数,首先检查是否设置了投票,如果 - 它也调用 isOfficeIdMatching
函数.
编辑: 要检查这两种情况的结果,请删除 JSON 对象中的投票对象。 参见 app.js
中的 LoC 36-38//remove the vote object, to see another output.
vote: {
officeId: 8
}
编辑 2: 要获得简化的解决方案:Simplified Plnkr(由于 OP 的评论,没有 ng-if)
没有 ng-if 了。 isVoteSet
函数负责检查 officeId 是否匹配。如果没有设置投票,它只是 returns true。
<div ng-repeat="candidate in main.office.candidateProfiles | filter:main.isVoteSet | orderBy:'-vScore'">
{{candidate.fullName}}
</div>
新的父函数:
vm.isVoteSet = function(candidate) {
if(vm.office.vote != null) {
return vm.isOfficeIdMatching(candidate);
}
return true;
}
编辑 3:
因为您的用例如下。
A) 如果设置了投票,过滤所有 candidateProfiles 以匹配已投票的人
B) 如果没有设置投票,就按vScore排序列表
这里是您问题的最终解决方案:Final Plnkr
HTML
<div ng-repeat="candidate in main.office.candidateProfiles| filter:main.isVoteSet | orderBy:main.whichOrderByPredicate">
<label>
<input type="checkbox" ng-click="main.setVote(candidate)"/>
{{candidate.fullName}}
</label>
</div>
JS
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var vm = this;
vm.office = {
name: "Metro Mayer",
candidateProfiles: [
{
candidateId: 5,
fullName: "John (Id 15, Score 1)",
vScore: 1
},
{
candidateId: 8,
fullName: "Linda (Id 8, Score 3)",
vScore: 3
},
{
candidateId: 120,
fullName: "Ben (Id 120, Score 2)",
vScore: 2
},
{
candidateId: 14,
fullName: "Rick (Id 14, Score 1)",
vScore: 1
},
{
candidateId: 15,
fullName: "Tesla (Id 15, Score 2)",
vScore: 2
}
],
vote: {}
};
/*Filtering functions
only used if a vote is set
*/
vm.isVoteSet = function(candidate) {
if(JSON.stringify(vm.office.vote) != "{}") {
return vm.isCandidateIdMatching(candidate);
}
return true;
};
vm.isCandidateIdMatching = function(candidate) {
return vm.office.vote.candidateId == candidate.candidateId;
};
/*Ordering functions
only used if NO vote is set
*/
vm.whichOrderByPredicate = function(candidate) {
return JSON.stringify(vm.office.vote) == "{}" ? -candidate.vScore : null;
};
/* Application logic */
vm.setVote = function(candidate) {
//unset if already set
if(vm.office.vote.candidateId == candidate.candidateId) {
vm.office.vote = {};
}
//else set the vote
else {
vm.office.vote.candidateId = candidate.candidateId
}
};
});