md-tabs:从 ui-router 内部调用函数时,为 md-selected 设置变量不起作用 [英] md-tabs: setting variable for md-selected not working when calling function from inside ui-router
问题描述
我有一个包含 md-tabs
的 ui-router
模板,其中一些标签是静态的,其他标签是使用 ng-repeat
动态创建的迭代数据模型的给定数组.
在那些动态创建的选项卡中,有三个按钮可以执行以下操作
- 将标签向左移动一个位置
- 将标签向右移动一个位置
move tab
按钮调用同一控制器内的函数.当前显示的选项卡的 $index
值以及所需的方向(-1
向左移动,1
向右移动)被传递到函数.
因此视图的 HTML 片段如下所示:
<md-card><md-tabs md-dynamic-height md-border-bottom md-autoselect md-swipe-content md-selected="selectedTab"><md-tab id="{{ 'tab' + $index }}" data-ng-repeat="tabs 中的tabs track by $index"><md-tab-label>Tab {{ $index + 1 }}</md-tab-label><md-tab-body><md-card-title><md-card-title-text><div flex layout="row"><div flex><span class="md-headline">Tab {{ $index + 1 }}</span></div><div flex align="right"><md-button ng-click="moveTab(-1, $index)">向左移动标签</md-button><md-button ng-click="moveTab(1, $index)">向右移动标签</md-button>
</md-card-title-text></md-card-title><md-card-content><p>这是标签 {{ $index + 1 }}</p></md-card-content></md-tab-body></md-tab></md-tabs></md-card></md-content>
移动标签的功能在MainController
中实现为:
$scope.moveTab = function(direction, TabIdx) {var staticTabs = 3var arr = $scope.tabsvar fromIdx = 扇区Idxvar toIdx = tabIdx + 方向//更正 `toIdx` 以防止第一个/最后一个数组元素的索引溢出如果(toIdx <0){toIdx = arr.length - 1} else if (toIdx > arr.length-1) {toIdx = 0}别的 {;//这里什么都不用做,因为`toIdx` 不需要更正}var tab = arr.splice(fromIdx, 1)[0]arr.splice(toIdx, 0, tab)$scope.selectedTab = staticTabs + toIdxconsole.log($scope.selectedTab)}
点击所需按钮移动标签后,根据需要显示相应标签邻居的数据.这表明操作 $scope.tabs
数组是正确的.此外,日志消息显示即使是 $scope.selectedTab
的新值也计算正确.但是,视图中未选择新选项卡.
这让我很困惑,因此两个变量 $scope.tabs
和 $scope.selectedTab
都定义在同一个控制器中,并且应该是同一个 $scope 的一部分
实例.此外,操纵的 $scope.tabs
数组在其他视图中使用并以新顺序显示选项卡数据,而 $scope.selectedTab
的新值没有似乎可用,并且显示的选项卡没有改变.
这是一个作用域继承问题,因为使用对象以外的其他数据类型的数据绑定在继承父作用域时没有双向绑定.
查看文档:
<块引用>作用域继承通常很简单,你通常不会甚至需要知道它正在发生...直到您尝试 2 路数据绑定(即,表单元素,ng-model)到基元(例如,数字,字符串,boolean) 在子作用域内在父作用域上定义.它不像大多数人期望的那样工作.发生什么了是子作用域拥有自己的属性,可以隐藏/隐藏同名的父属性.这不是 AngularJS 的东西做——这就是 JavaScript 原型继承的工作原理.新的AngularJS 开发人员通常没有意识到 ng-repeat、ng-switch、ng-view 和 ng-include 都创建了新的子作用域,所以问题是当涉及这些指令时,通常会出现.[...]
遵循以下原则可以轻松避免原语的这个问题最佳实践"的总是有一个'.'在你的 ng-models [...]
修改后
selectedTab
到
selectedTab.inputTab
在给定的 HTML 和 JS 片段中,一切都按预期工作.
I have a ui-router
template containing md-tabs
from which some tabs are static, others are created dynamically using ng-repeat
iterating through a given array of the data model.
Inside those dynamically created tabs there are three buttons to do the following
- move tab left by one position
- move tab right by one position
The move tab
buttons call a function inside the same controller. The $index
value of the currently shown tabs as well as the desired direction (-1
for moving left, 1
for moving right) are passed to the function.
So the HTML-snippet for the view looks as follows:
<md-content flex layout-padding>
<md-card>
<md-tabs md-dynamic-height md-border-bottom md-autoselect md-swipe-content md-selected="selectedTab">
<md-tab id="{{ 'tab' + $index }}" data-ng-repeat="tab in tabs track by $index">
<md-tab-label>Tab {{ $index + 1 }}</md-tab-label>
<md-tab-body>
<md-card-title>
<md-card-title-text>
<div flex layout="row">
<div flex><span class="md-headline">Tab {{ $index + 1 }}</span></div>
<div flex align="right">
<md-button ng-click="moveTab(-1, $index)">Move tab left</md-button>
<md-button ng-click="moveTab(1, $index)">Move tab right</md-button>
</div>
</div>
</md-card-title-text>
</md-card-title>
<md-card-content>
<p>This is tab {{ $index + 1 }}</p>
</md-card-content>
</md-tab-body>
</md-tab>
</md-tabs>
</md-card>
</md-content>
The function moving the tabs is implemented in MainController
as:
$scope.moveTab = function(direction, TabIdx) {
var staticTabs = 3
var arr = $scope.tabs
var fromIdx = sectorIdx
var toIdx = tabIdx + direction
// correct `toIdx` in order to prevent index overflow for first/last array element
if (toIdx < 0) {
toIdx = arr.length - 1
} else if (toIdx > arr.length-1) {
toIdx = 0
}
else {
; // nothing to do here since `toIdx` does not need to be corrected
}
var tab = arr.splice(fromIdx, 1)[0]
arr.splice(toIdx, 0, tab)
$scope.selectedTab = staticTabs + toIdx
console.log($scope.selectedTab)
}
After clicking the desired button to move a tab, the data of the according tab neigbour is displayed as desired.
This shows that maniupulating the $scope.tabs
array works correctly. Additionally the log-message shows that even the new value for $scope.selectedTab
is calculated correctly.
However, the new tab is not selected in the view.
This confuses me hence both variables $scope.tabs
and $scope.selectedTab
are defined in the same controller and should be part of the same $scope
instance.
In addition, the manipulated $scope.tabs
array is used in other views and shows the tab data in the new order, whereas the new value for $scope.selectedTab
does not seem to be available and the shown tab does not change.
This was a problem of scope inheritance since data-bindings using other datatypes than objects do not have two-way-binding when inheriting the parent scope.
See the docs:
Scope inheritance is normally straightforward, and you often don't even need to know it is happening... until you try 2-way data binding (i.e., form elements, ng-model) to a primitive (e.g., number, string, boolean) defined on the parent scope from inside the child scope. It doesn't work the way most people expect it should work. What happens is that the child scope gets its own property that hides/shadows the parent property of the same name. This is not something AngularJS is doing – this is how JavaScript prototypal inheritance works. New AngularJS developers often do not realize that ng-repeat, ng-switch, ng-view and ng-include all create new child scopes, so the problem often shows up when these directives are involved. [...]
This issue with primitives can be easily avoided by following the "best practice" of always have a '.' in your ng-models [...]
After changing
selectedTab
to
selectedTab.inputTab
in both the given HTML- and JS-snippets everything works as expected.
这篇关于md-tabs:从 ui-router 内部调用函数时,为 md-selected 设置变量不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!