【问题标题】:AngularJS scoping issue with multiple directives多个指令的AngularJS范围问题
【发布时间】:2015-01-28 23:44:50
【问题描述】:

我正在为名为 trNgGrid 的网格实现添加一些键盘导航支持。我有一些代码可以工作,但是我认为范围界定问题是胜利和失败之间的问题。

我想要达到的目标:

  1. 鼠标悬停时,将网格项标记为“已激活”并添加“活动”类
  2. 在上/下/左/右箭头键上选择下一个网格行 - 对其应用“激活”状态和活动类。

我已经实现了 mousedown 功能,并且运行良好。在初始化时,我有一个名为 gridOptions.selectedIndex 的选项,默认为 0。此选项在主父指令中定义 - 参见 plnkr trNgGrid.js 第 945 行

selectedIndex: '=?' //not sure why the ? really - just mimicking others in this grid directive

在鼠标悬停时,调用一个函数,将 gridOptions.selectedIndex 设置为被鼠标悬停的行的索引。如果 $index==gridOptions.selectedIndex,每一行都应用了一个 ng-class 来设置活动类。

显示如何使用 ng-repeat 和我的 ng-class 设置输出表行的代码 - 请参阅 plnkr trNgGrid.js 第 710-714 行

templatedBodyRowElement.attr("ng-repeat", "gridDisplayItem in filteredItems");
templatedBodyRowElement.attr("ng-init", "gridItem=gridDisplayItem.$$_gridItem");
templatedBodyRowElement.attr("ng-class", "{'" + TrNgGrid.rowSelectedCssClass + "':$index==gridOptions.selectedIndex}");
templatedBodyRowElement.attr("ng-mouseover", "handleMouseOver($index, $event)");

bodyDirective(鼠标处理逻辑) - 参见 plnkr trNgGrid.js 第 1086 行

scope.handleMouseOver = function(index, $event) {
  controller.handleMouseOver(index, $event);
}

handlMouseOver() 的控制器函数 - 参见 plnkr trNgGrid.js 第 461 行

GridController.prototype.handleMouseOver = function (index, $event) {
  this.gridOptions.selectedIndex = index;
}

现在,对于按键... 在组成 trNgGrid 的几个指令之一中,我正在注入 $document,并添加一个 $document 监听器(我需要在页面上可用网格时随时监听箭头键 - 永远不会超过一个一个页面上的网格)。对于与正确的键代码匹配的每个 keydown,我调用一个适当地更新 gridOptions.selectedIndex 的函数。基于 ng-class 属性(活动:$index==gridOptions.selectedIndex),理论上这应该将“活动”类和 css 样式应用于行。然而,这并没有发生。我试图以与 mouseover 函数相同的方式引用 gridOptions,但我想知道 ng-repeat 及其作用域行为是否会以某种方式干扰?

包含 $document 侦听器的指令 - 参见 plnkr trNgGrid 第 1071 行

.directive(bodyDirective, [ "$document",
    function ($document) {
        return {
            restrict: 'A',
            require: '^' + tableDirective,
            scope: true,
            compile: function (templateElement, tAttrs) {
                return {
                    pre: function (scope, compiledInstanceElement, tAttrs, controller) {
                        scope.toggleItemSelection = function (item, $event) {
                            controller.toggleItemSelection(scope.filteredItems, item, $event);
                        };
                        scope.doRowClickAction = function (item, $event) {
                            controller.doRowClickAction(scope.filteredItems, item, $event);
                        };
                        scope.handleMouseOver = function(index, $event) {
                            controller.handleMouseOver(index, $event);
                        }
                        scope.navigateRows = function(dir, $event) {
                            controller.navigateRows(dir);
                        }
                        scope.selectRow = function($event) {
                            controller.selectRow();
                        }
                        scope.navigatePage = function(dir, $event) {
                            controller.navigatePage(dir);
                        }
                    },
                    post: function(scope, iElem, tAttrs, controller){
                        // Keyboard Navigation of table
                        $document.on("keydown", function(event) {
                            var keyCode = event.which;
                            switch (keyCode) {
                                case 38: //up arrow 
                                case 37: //left arrow 
                                    scope.navigateRows("up");
                                    break;
                                case 40: //down arrow 
                                case 39: //right arrow 
                                    scope.navigateRows("down");
                                    break;
                                case 13: //enter
                                    scope.selectRow();
                                    break;
                                case 33: //page up 
                                    scope.navigatePage("up");
                                    break;
                                case 34: //page down
                                    scope.navigatePage("down");
                                    break;
                            }                                    
                        });
                    }
                };
            }
        };
    }
])

具有向上/向下/向左/向右/箭头逻辑的控制器函数 - 参见 plnkr trNgGrid 第 468 行

GridController.prototype.navigateRows = function (dir){
    var count = this.gridOptions.items.length;
    if (count > 1) {
        if (dir === "up") {
            if (this.gridOptions.selectedIndex > 0) {
                this.gridOptions.selectedIndex -= 1;            
            }
        } else {
            if (this.gridOptions.selectedIndex < count-1) {
                this.gridOptions.selectedIndex += 1;
            }
        }
        console.log(this.gridOptions.selectedIndex);
    }
}

由于代码太多,我可能要求太多,让别人看这么多代码,但我创建了一个 plunk 来展示我所做的。

http://plnkr.co/edit/y8lXuDa7zodzW4iWG2UV?p=preview

【问题讨论】:

    标签: angularjs angularjs-scope


    【解决方案1】:

    解决了。这个问题让我了解了我的问题以及必须做的事情:

    How do I update an angularjs page after a scope update?

    scope.$apply() 是必需的。我继续将它包裹在每个最终修改范围的函数调用中。

    scope.$apply(function(){
      scope.navigateRows("up");
    });
    

    【讨论】:

      猜你喜欢
      • 2015-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-28
      相关资源
      最近更新 更多