md-tabs:从 ui-router 内部调用函数时,为 md-selected 设置变量不起作用 [英] md-tabs: setting variable for md-selected not working when calling function from inside ui-router

查看:27
本文介绍了md-tabs:从 ui-router 内部调用函数时,为 md-selected 设置变量不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含 md-tabsui-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屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆