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-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>
移动标签的功能在MainController
中实现为:
$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)
}
点击需要移动标签的按钮后,根据需要显示相应标签邻居的数据。
这表明操作 $scope.tabs
数组工作正常。此外,日志消息显示 $scope.selectedTab
的新值也计算正确。
但是,在视图中未选择新选项卡。
这让我感到困惑,因此变量 $scope.tabs
和 $scope.selectedTab
都在同一个控制器中定义,并且应该是同一个 $scope
实例的一部分。
此外,被操纵的 $scope.tabs
数组用于其他视图并以新顺序显示选项卡数据,而 $scope.selectedTab
的新值似乎不可用并且显示的选项卡没有改变。
这是范围继承的问题,因为使用对象以外的其他数据类型的数据绑定在继承父范围时没有双向绑定。
查看文档:
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 [...]
改变后
selectedTab
到
selectedTab.inputTab
在给定的 HTML- 和 JS 片段中,一切都按预期工作。
我有一个包含 md-tabs
的 ui-router
模板,其中一些选项卡是静态的,其他选项卡是使用 ng-repeat
迭代数据模型的给定数组动态创建的。
在那些动态创建的选项卡中,有三个按钮可以执行以下操作
- 将制表符向左移动一位
- 标签向右移动一位
move tab
按钮调用同一控制器内的函数。当前显示的选项卡的 $index
值以及所需的方向(-1
向左移动,1
向右移动)被传递给函数。
因此视图的 HTML- 片段如下所示:
<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>
移动标签的功能在MainController
中实现为:
$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)
}
点击需要移动标签的按钮后,根据需要显示相应标签邻居的数据。
这表明操作 $scope.tabs
数组工作正常。此外,日志消息显示 $scope.selectedTab
的新值也计算正确。
但是,在视图中未选择新选项卡。
这让我感到困惑,因此变量 $scope.tabs
和 $scope.selectedTab
都在同一个控制器中定义,并且应该是同一个 $scope
实例的一部分。
此外,被操纵的 $scope.tabs
数组用于其他视图并以新顺序显示选项卡数据,而 $scope.selectedTab
的新值似乎不可用并且显示的选项卡没有改变。
这是范围继承的问题,因为使用对象以外的其他数据类型的数据绑定在继承父范围时没有双向绑定。
查看文档:
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 [...]
改变后
selectedTab
到
selectedTab.inputTab
在给定的 HTML- 和 JS 片段中,一切都按预期工作。