Angular作用域和ng-click / ng-show用于设置多个div
Angular作用域和ng-click / ng-show用于设置多个div
我正在寻求帮助,解决我已经有的代码。
主要目标是能够点击任何加号图标,并在其他所有div块上放置一个覆盖层。
并且当点击加号图标时,它还会在右侧显示一个div块。
当单击块2时,您将看到它实现了所有用途。
当任何加号图标被点击时,我正在寻找一种有效的方法来使用Angular实现这一点。
这只是我在此处展示的一个小样本,实际上会有10到20个块需要覆盖。
如果有人能看到一种使用更少的代码,并更好地利用作用域的方法,那将非常感激。
我已经看过许多选项,比如在这里的帖子中。
试过了,但它不想工作...
data-ng-class="{coverThisBlock: value2 == 'off',coverThisBlock: value == 'on'}"
如果我必须使用这种类型的选项,甚至说10个块,那将是一团糟。
主要问题
有没有更好的Angular方法使其起作用...当单击任何加号图标时,它会更改作用域,然后被ngclass和ng-show使用?
如何在此示例中正确连接作用域?
非常感谢。
我已经设置了一个工作中的FIDDLE HERE。
这是Avijit Gupta的最终工作示例。
1 Hello
2 Hello
3
4 Hello
回答与ng-repeat有关的问题
ng-repeat可以为每个不同的div使用多个CSS类吗
显然可以。
通过使用类似于这样的作用域id...
和CSS像这样...
.block-1 {...
更新
糟糕,每次只能选择一个。嗯...我写的大部分内容都适用。
唯一的区别是JavaScript。我们不再有一个所选块的数组,而是有一个代表所选块的数字。
this.blocks = Array.apply(null, Array(10)).map(function (val, index) {return index;}); this.activeIndex = null; this.isActive = function(index) { return that.activeIndex === index; }; this.hasSelected = function() { return that.activeIndex !== null; }; this.selectBlock = function(index) { if (that.activeIndex === index) { that.activeIndex = null; } else { that.activeIndex = index; } };
看,好的JavaScript代码很容易维护,即使需求发生变化(或我发现它们发生了变化)。
(实际上,我们可以不使用这些辅助函数,但是我们使用它们是为了更漂亮的代码和可能的封装。)
原始答案
我希望我已经解释了为什么我们应该在Fiddle中做这些事情,并提供了可靠的参考/进一步阅读材料。
先搞清楚
- 不要使用
$scope
。我喜欢controller as
语法。在JS中,你使用this.prop
和HTML中,你使用myCtrlAs.prop
。 文档 - 这是一个CSS问题。利用
:not()
。
两个原则:KISS和DRY
所以我们有一个同样复制粘贴的代码块问题。就像 @avijit 说的,你应该使用 ng-repeat
指令。
//This entire block will be repeated
对于每一行,我们需要跟踪它是否被选中。遵循KISS原则,唯一需要跟踪的状态就是这个。
否则,事情会变得太复杂。
//each element represents the state of a row this.blocks = [0,0,0,0,0];
所以这个块数组用于 ng-repeat
。
你会问,我们如何跟踪哪些要变暗,哪些是活动的?
答案是...等着吧。
你不用跟踪
相反,我们使用在控制器上的函数获取有关单个 blocks
变量的信息。你可以反对我的措辞,但请注意我说了“跟踪”吗?再次强调,不要存储重复的状态数据。根据我的经验,这变成了一场噩梦。
(实际上,我们可以不使用这些辅助函数,但是我们使用它们是为了更漂亮的代码和可能的封装。)
所以我想指出的第一个函数是:
this.hasSelected = function() { return that.blocks.indexOf(true) !== -1; };
这是用来做什么的?你说对了!是为了确定是否应该“遮盖”未选中的行。
使用CSS-它很有用!
所以我们有条件地应用 .has-selected
类到包装器上。
所以,只有当它有一个 .has-selected
的祖先时,“封面”才适用,我们有
has-selected :not(.active) > .col-sm-4 { width: 33%; height: inherit; background-color: rgba(00,00,00,0.8); z-index: 9; } .has-selected :not(.active) .col-sm-4 { @media (max-width:420px){ width: 80%; } }
回到 ng-repeat
哦,到现在为止,你应该知道 $index
被用于访问当前HTML在 ng-repeat
中的索引。(文档和 SO 线程)
{{$index}}
结论
- 阅读文档
- 不要试图用一个工具做所有的事情
- 如果你认为我没有特别好地解释某些东西,只需询问。
另外,我认为我破坏了一些样式。希望你能自己修复它。
编辑 (根据提问者的评论):
- 只能有一个被点击吗?或者如果另一个被打开/点击,第一个被打开的将被重置和关闭
这将使您的代码简化近2倍。
初始状态:
- 没有选择任何块。
- 没有块被覆盖。
代码:
$scope.setToInitialState = function() { $scope.blocks.forEach(function(block) { $scope.isSelected[block.id] = false; $scope.isCovered[block.id] = false; }); };
触摸状态:
- 切换所点击块的选择状态。(在选择和取消选择之间切换)
- 如果选择,则覆盖和取消选择所有其他块。
- 如果取消选择,则将应用程序带回初始状态。
代码:
$scope.selectBlock = function(id) { $scope.isSelected[id] = !$scope.isSelected[id]; $scope.isCovered[id] = false; if ($scope.isSelected[id]) { $scope.blocks.forEach(function(block) { if (block.id !== id) { $scope.isCovered[block.id] = true; $scope.isSelected[block.id] = false; } }); } else { $scope.setToInitialState(); } };
- 演示使用相同的设置块大小,但实际使用的所有div块都具有不同的高度和宽度。并且每个块都是不同的图像
您应该考虑使用ng-src
。
假设您可能从DB检索所有这些内容。然后,如果可能,您可以将每个图像放在固定大小的div中,以使它们的大小相同。
- 另外,显示分为2个竖直半屏幕部分
可以通过稍微调整css来实现。
原始答案:
假设您的应用程序具有2种状态:
- 初始状态(未触摸)
- 触摸状态
最初,您处于初始状态:
- 没有显示正确的div。
- 所有图标都是“加号”(没有“减去”)
- 没有块被覆盖。
代码:
$scope.setToInitialState = function() { $scope.plusCount = 0; $scope.blocks.forEach(function(block) { $scope.isPlus[block.id] = true; $scope.isShowDiv[block.id] = false; $scope.isCoverBlock[block.id] = false; $scope.plusCount += 1; }); };
当您处于触摸状态时:
- 所有具有“加号”图标的块都被覆盖。
- 仅显示未覆盖的那些块的正确div。
代码:
// Run when user clicks on the 'plus' or 'minus' icon. $scope.selectBlock = function(id) { $scope.isPlus[id] = !$scope.isPlus[id]; // toggle between 'plus' and 'minus' icons if ($scope.isPlus[id]) { $scope.plusCount += 1; } else { $scope.plusCount -= 1; } $scope.blocks.forEach(function(block) { if ($scope.isPlus[block.id]) { $scope.isCoverBlock[block.id] = true; } else { $scope.isCoverBlock[block.id] = false; } $scope.isShowDiv[block.id] = !$scope.isCoverBlock[block.id]; }); };
因此,基本上当用户与视图交互并实际点击图标时,他/她进入touched state
(运行上面的代码)。
只有当所有图标都是'plus'时,用户必须被发送到initial state
:
if ($scope.plusCount === $scope.blocks.length) { $scope.setToInitialState(); }
更改HTML代码:
- 将
ng-init =“setToInitialState()”
添加到最外面的div中,以便最初处于初始状态。
代码:
- 使用
ng-repeat
,而不是为每个块复制和粘贴代码:
代码:
{{block.id}} Hello
希望这对您有所帮助!