我想对ng-show
使用需要首先评估的对象属性。
我有一个包含lanOption
(语言)对象的数组,我想在select
元素中显示。是否显示语言取决于同样存在于范围内的变量couID
(国家/地区)。
我希望通过附加属性在对象中包含关于显示或隐藏语言的逻辑,然后由ng-show
使用,如下所示:
$scope.lanOptions = [
{name: "English", ngShow: "1"},
{name: "Danish", ngShow: "$scope.couID='DK'"},
{name: "French", ngShow: "$scope.couID='FR' || $scope.couID='BE'"},
{name: "Dutch", ngShow: "$scope.couID='NL' || $scope.couID='BE'"}
]
(应始终显示英文,仅在选择丹麦时显示丹麦语等)
<select>
<option ng-repeat="o in lanOptions" ng-show="{{o.ngShow}}" value="{{o.name}}">{{o.name}}</option>
</select>
这里的重要部分是ng-show
属性 - 有没有办法让它发挥作用?和/或有没有更好的方法让我失踪?我试过了filter:
,但没有成功。
谢谢!
澄清一下:这个例子实际上非常简化为我实际想做的事情。在我的实际问题中,还有许多变量值(可能)会影响每个选项的可见性。
举个例子,考虑
{name: 'Basque', ngShow: "($scope.couID=='ES' || $scope.couID=='FR') && $scope.inclMinority==true"}
或
{name: 'German', ngShow: "$scope.couID=='DE' ||
$scope.couID=='AU' ||
($scope.couID=='BE' && $scope.inclMinority==true)"}
,或更复杂的表达。
这就是我不只是将couID
数组作为属性添加到每个语言对象的原因 - 如果我之前没有明确提及,我很抱歉。
答案 0 :(得分:1)
使用ngShow: "$scope.couID='DK'"}
在模型@ $scope.
中修复范围变量名称并不是一个好主意。如果您计划更改包含范围的变量名称,或者将此模型移植到某个位置,该怎么办?变得无法使用对属性名称$scope.couID
进行条件检查的情况也是如此(可能您将其作为一种灵活性添加,以便您可以针对范围内的多个变量放置过滤条件,例如couID
和各种不同的条件)。但是,即使您在ngShow中使用插值,绑定ngShow
中的条件表达式也不会被评估,(可能您也可能会遇到语法错误)。
对于ng-show使用插值也不是一个好主意,因为它会查找即使是字符串"false"
的truthy表达式(如果在布尔值上使用ng-show和插值,则会对其进行求值)价值,在你有条件的情况下离开,无论如何都不会默认工作),你最终会显示所有选项。
您应该退出ng-repeat用法来创建选择,而是开始使用 ng-options。
通过保持模型中的条件,您可以使用 $parse 获取项目本身时评估ng-show表达式的一种方法,为什么要为ng-show
添加不需要的监视?: -
在控制器中注入$parse
,以便根据范围解析表达式: -
.controller('MainCtrl', function($scope, $parse) {
//.....
//In your method just return only necessary dropdown values
$scope.getLanOptionsForCountry = function(){
//Just filter it based on selected country and populate the select.
return $scope.lanOptions.filter(function(itm){
return $parse(itm.ngShow)($scope);
});
}
//...
你的选择看起来就像: -
<!-- Just added for the demo to select a country -->
<select ng-model="couID" ng-options = "country.code as country.name for country in countries">
<option value="">--Choose one--</option>
</select>
<!-- This will be your selected, just added a placeholder option as well and an ngModel -->
<select ng-model="language" ng-options = "lang.name for lang in getLanOptionsForCountry()">
<option value="">--Choose one--</option>
</select>
<强> Plnkr - Demo 强>
或者您甚至可以通过删除其中的条件使您的视图模型更具可移植性,并为国家/地区代码设置过滤器,仅显示这些选项。
//Add a filter property which if present will display only for those country code else if will always display
$scope.lanOptions = [
{name: "English"},
{name: "Danish", filter: ["DK"]},
{name: "French", filter: ["FR", "BE"]},
{name: "Dutch", filter:["NL", "BE"]}
];
$scope.getLanOptionsForCountry = function(){
return $scope.lanOptions.filter(function(itm){
return !itm.filter || (itm.filter.indexOf($scope.couID) + 1);
});
}
<强> Plnkr2 - Demo 强>
请参阅填充和对Array.Filter
的支持答案 1 :(得分:0)
我会将您的语言选项更改为
$scope.lanOptions = [
{name: "English", countries: ["EN"]},
{name: "Danish", countries: ["DK"]},
{name: "French", countries: ["FR","BE"]},
{name: "Dutch", countries: ["NL","BE"]}
]
并将ng-show更改为范围上的函数调用:
ng-show="showCountry(o)"
关于范围:
$scope.showCountry = function (lanOption) {
return (lanOption.countries.indexOf("EN")> -1
||lanOption.countries.indexOf($scope.couID)>-1)
}
编辑:实际上,进一步考虑了这一点,你可以放弃所有的ng-show,并通过调用一个简单返回的函数来替换你的ng-repeat 你需要的东西:
$scope.getLanOptionsForCountry = function () {
return @scope.lanOptions.filter( function( item) {
return item.countries.indexOf("EN")>-1 ||
item.countries.indexOf($scope.couID)
});
}
然后
<select>
<option ng-repeat="o in getLanOptionsForCountry()" value="{{o.name}}">{{o.name}}</option>
</select>