AngularJS:ng-repeat 和 scoped ng-click
AngularJS: ng-repeat and scoped ng-click
我有一系列由 ng-repeat 填充的列表项。可见性由简单的 ng-click 和 ng-show 关系控制。在大多数情况下,这工作得很好,但我希望能够使用全局按钮控制 show/hide 行为,该按钮将显示或隐藏列表中的 all 可用项目.
公平披露:我对 AngularJS 还是很陌生。我知道这是一个范围界定问题,但我不确定如何解决它。这几乎可以肯定是不知道要问正确的问题的情况。
我这里有一个 jsfiddle 来展示我的困难:http://jsfiddle.net/36BYs/838/
样本HTML:
<div ng-controller="MainCtrl">
<span ng-show="!IsVisible" ng-click="isVisible = !isVisible;" >
(show/hide all)
<i class="fa fa-minus-square-o fa-small"></i>
</span>
<ul>
<li ng-repeat="mentor in mentors">
<a ng-click="isVisible = !isVisible;">show/hide</a>
<span ng-show="isVisible">{{mentor}}</span>
</li>
</ul>
</div>
示例 JS:
var app = angular.module('myApp', []);
function MainCtrl( $scope ) {
$scope.isVisible = true;
$scope.mentors = [ 'Jonathan', 'Nathan', 'Chris', 'Brian', 'Timothy' ];
}
只要您没有单独切换列表项之一,它就可以正常工作。但是如果您在特定行上单击 show/hide,则全局 ng-click 将失去对该项目的控制。
提前感谢您提供的任何建议。
看来,在初始渲染中,angular 正在尝试为每位导师评估 isVisible
。因为 mentor.isVisible
将是 undefined
,angular 框架使用父作用域的 isVisible
.
但是,当你切换一个特定的导师时,你有效地为那个特定的 mentor
字符串分配了一个 isVisible
布尔值 属性。 (因为您可以愉快地将附加属性附加到 javascript 中的 string
)。
在此之后,您可以切换 show/hide all
,这将影响每个尚未分配给 isVisible
属性 的导师。
它展示了 AngularJS 的初始版本中的范围界定是多么混乱。
这是一个可行的答案:http://jsfiddle.net/fkw5923t/
我做了一些修改:
- 我没有为
$scope
赋值,而是使用 controllerName as mnemonic
语法。在控制器代码中,我将值分配给 this
而不是 $scope
。我更喜欢这种方法,因为现在范围界定清晰明了
- 我已将
mentor
从字符串更改为对象,包含两个值:name
和 isVisible
。同样,这现在使范围规则清晰明了。
HTML:
<div ng-controller="MainCtrl as mainCtrl">
<span class = "clickable" ng-click="mainCtrl.isVisible = !mainCtrl.isVisible;" >
(show/hide all)
<i class="fa fa-minus-square-o fa-small"></i>
</span>
<ul ng-show="mainCtrl.isVisible">
<li ng-repeat="mentor in mainCtrl.mentors">
<a class = "clickable" ng-click="mentor.isVisible = !mentor.isVisible;">show/hide</a>
<span ng-show="mentor.isVisible">{{ mentor.name }}</span>
</li>
</ul>
</div>
javascript:
var app = angular.module('myApp', []);
function MainCtrl() {
this.isVisible = true;
var mentorNames = ['Jonathan', 'Nathan', 'Chris', 'Brian', 'Timothy'];
this.mentors = mentorNames.map(
name => {
return {
name:name,
isVisible:true
};
}
);
}
var app = angular.module('myApp', []);
app.controller("myCtrl", function ($scope) {
$scope.mentors = [
'Jonathan',
'Nathan',
'Chris',
'Brian',
'Timothy'
];
$scope.showAll = function() {
$scope.visibleMentors = $scope.mentors.slice();
};
$scope.hideAll = function() {
$scope.visibleMentors = [];
};
$scope.isVisible = function(mentor) {
return $scope.visibleMentors.includes(mentor);
};
$scope.show = function(mentor) {
$scope.visibleMentors.push(mentor);
};
$scope.hide = function(mentor) {
$scope.visibleMentors.splice($scope.visibleMentors.indexOf(mentor), 1);
};
$scope.showAll();
});
a {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myCtrl">
<button ng-click="showAll()">show all</button>
<button ng-click="hideAll()">hide all</button>
<ul>
<li ng-repeat="mentor in mentors">
<a ng-show="isVisible(mentor)" ng-click="hide(mentor)">hide</a>
<a ng-show="!isVisible(mentor)" ng-click="show(mentor)">show</a>
<span ng-show="isVisible(mentor)">
{{mentor}}
</span>
</li>
</ul>
</div>
</div>
虽然其他评论很有用,但用户 miqid 的评论为我的特定需求提供了最佳答案:
As you're aware, ng-repeat introduces a separate scope so that each isVisible underneath no longer tracks the parent isVisible. One solution is to explicitly track isVisible per item in addition to tracking a parent visibility state that overrides item-level one if necessary. Demo—jsfiddle.net/uLykhg0z – miqid 14 hours ago
jsfiddle 是 Andrew Shepherd 解决方案 (jsfiddle.net/uLykhg0z) 的变体:
HTML:
<div ng-controller="MainCtrl">
<span ng-show="!IsVisible" class = "clickable" ng-click="toggleVisibility()" >
(show/hide all)
<i class="fa fa-minus-square-o fa-small"></i>
</span>
<ul>
<li ng-repeat="mentor in mentors">
<a class = "clickable" ng-click="mentor.isVisible = !mentor.isVisible;">show/hide</a>
<span ng-show="mentor.isVisible">{{mentor.name}}</span>
</li>
</ul>
</div>
JS:
var app = angular.module('myApp', []);
function MainCtrl( $scope ) {
var isVisible = true;
$scope.mentors = [
{ name: 'Jonathan', isVisible: true },
{ name: 'Nathan', isVisible: true },
{ name: 'Chris', isVisible: true },
{ name: 'Brian', isVisible: true },
{ name: 'Timothy', isVisible: true },
];
$scope.toggleVisibility = function () {
isVisible = !isVisible;
$scope.mentors = $scope.mentors.map(function (mentor) {
mentor.isVisible = isVisible;
return mentor;
});
};
}
这使我能够容纳一些我必须在树结构中处理的更复杂的嵌套。
再次感谢大家的帮助!
我有一系列由 ng-repeat 填充的列表项。可见性由简单的 ng-click 和 ng-show 关系控制。在大多数情况下,这工作得很好,但我希望能够使用全局按钮控制 show/hide 行为,该按钮将显示或隐藏列表中的 all 可用项目.
公平披露:我对 AngularJS 还是很陌生。我知道这是一个范围界定问题,但我不确定如何解决它。这几乎可以肯定是不知道要问正确的问题的情况。
我这里有一个 jsfiddle 来展示我的困难:http://jsfiddle.net/36BYs/838/
样本HTML:
<div ng-controller="MainCtrl">
<span ng-show="!IsVisible" ng-click="isVisible = !isVisible;" >
(show/hide all)
<i class="fa fa-minus-square-o fa-small"></i>
</span>
<ul>
<li ng-repeat="mentor in mentors">
<a ng-click="isVisible = !isVisible;">show/hide</a>
<span ng-show="isVisible">{{mentor}}</span>
</li>
</ul>
</div>
示例 JS:
var app = angular.module('myApp', []);
function MainCtrl( $scope ) {
$scope.isVisible = true;
$scope.mentors = [ 'Jonathan', 'Nathan', 'Chris', 'Brian', 'Timothy' ];
}
只要您没有单独切换列表项之一,它就可以正常工作。但是如果您在特定行上单击 show/hide,则全局 ng-click 将失去对该项目的控制。
提前感谢您提供的任何建议。
看来,在初始渲染中,angular 正在尝试为每位导师评估 isVisible
。因为 mentor.isVisible
将是 undefined
,angular 框架使用父作用域的 isVisible
.
但是,当你切换一个特定的导师时,你有效地为那个特定的 mentor
字符串分配了一个 isVisible
布尔值 属性。 (因为您可以愉快地将附加属性附加到 javascript 中的 string
)。
在此之后,您可以切换 show/hide all
,这将影响每个尚未分配给 isVisible
属性 的导师。
它展示了 AngularJS 的初始版本中的范围界定是多么混乱。
这是一个可行的答案:http://jsfiddle.net/fkw5923t/
我做了一些修改:
- 我没有为
$scope
赋值,而是使用controllerName as mnemonic
语法。在控制器代码中,我将值分配给this
而不是$scope
。我更喜欢这种方法,因为现在范围界定清晰明了 - 我已将
mentor
从字符串更改为对象,包含两个值:name
和isVisible
。同样,这现在使范围规则清晰明了。
HTML:
<div ng-controller="MainCtrl as mainCtrl">
<span class = "clickable" ng-click="mainCtrl.isVisible = !mainCtrl.isVisible;" >
(show/hide all)
<i class="fa fa-minus-square-o fa-small"></i>
</span>
<ul ng-show="mainCtrl.isVisible">
<li ng-repeat="mentor in mainCtrl.mentors">
<a class = "clickable" ng-click="mentor.isVisible = !mentor.isVisible;">show/hide</a>
<span ng-show="mentor.isVisible">{{ mentor.name }}</span>
</li>
</ul>
</div>
javascript:
var app = angular.module('myApp', []);
function MainCtrl() {
this.isVisible = true;
var mentorNames = ['Jonathan', 'Nathan', 'Chris', 'Brian', 'Timothy'];
this.mentors = mentorNames.map(
name => {
return {
name:name,
isVisible:true
};
}
);
}
var app = angular.module('myApp', []);
app.controller("myCtrl", function ($scope) {
$scope.mentors = [
'Jonathan',
'Nathan',
'Chris',
'Brian',
'Timothy'
];
$scope.showAll = function() {
$scope.visibleMentors = $scope.mentors.slice();
};
$scope.hideAll = function() {
$scope.visibleMentors = [];
};
$scope.isVisible = function(mentor) {
return $scope.visibleMentors.includes(mentor);
};
$scope.show = function(mentor) {
$scope.visibleMentors.push(mentor);
};
$scope.hide = function(mentor) {
$scope.visibleMentors.splice($scope.visibleMentors.indexOf(mentor), 1);
};
$scope.showAll();
});
a {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myCtrl">
<button ng-click="showAll()">show all</button>
<button ng-click="hideAll()">hide all</button>
<ul>
<li ng-repeat="mentor in mentors">
<a ng-show="isVisible(mentor)" ng-click="hide(mentor)">hide</a>
<a ng-show="!isVisible(mentor)" ng-click="show(mentor)">show</a>
<span ng-show="isVisible(mentor)">
{{mentor}}
</span>
</li>
</ul>
</div>
</div>
虽然其他评论很有用,但用户 miqid 的评论为我的特定需求提供了最佳答案:
As you're aware, ng-repeat introduces a separate scope so that each isVisible underneath no longer tracks the parent isVisible. One solution is to explicitly track isVisible per item in addition to tracking a parent visibility state that overrides item-level one if necessary. Demo—jsfiddle.net/uLykhg0z – miqid 14 hours ago
jsfiddle 是 Andrew Shepherd 解决方案 (jsfiddle.net/uLykhg0z) 的变体:
HTML:
<div ng-controller="MainCtrl">
<span ng-show="!IsVisible" class = "clickable" ng-click="toggleVisibility()" >
(show/hide all)
<i class="fa fa-minus-square-o fa-small"></i>
</span>
<ul>
<li ng-repeat="mentor in mentors">
<a class = "clickable" ng-click="mentor.isVisible = !mentor.isVisible;">show/hide</a>
<span ng-show="mentor.isVisible">{{mentor.name}}</span>
</li>
</ul>
</div>
JS:
var app = angular.module('myApp', []);
function MainCtrl( $scope ) {
var isVisible = true;
$scope.mentors = [
{ name: 'Jonathan', isVisible: true },
{ name: 'Nathan', isVisible: true },
{ name: 'Chris', isVisible: true },
{ name: 'Brian', isVisible: true },
{ name: 'Timothy', isVisible: true },
];
$scope.toggleVisibility = function () {
isVisible = !isVisible;
$scope.mentors = $scope.mentors.map(function (mentor) {
mentor.isVisible = isVisible;
return mentor;
});
};
}
这使我能够容纳一些我必须在树结构中处理的更复杂的嵌套。
再次感谢大家的帮助!