AngularJS具有多个指令的范围问题

时间:2015-01-28 23:44:51

标签: angularjs angularjs-scope

我正在为名为trNgGrid的网格实现添加一些键盘导航支持。我有一些代码工作,但我相信范围问题是胜利与失败之间的关系。

我想要实现的目标:

  1. 在鼠标悬停时,将网格项标记为“已激活”并添加“有效”类
  2. 上/下/左/右箭头键选择下一个网格行 - 将“激活”状态和活动类应用于它。
  3. 我实现了mousedown功能,它运行良好。在初始化时,我有一个名为gridOptions.selectedIndex的选项,默认为0.此选项在主父指令中定义 - 请参阅plnkr trNgGrid.js第945行

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

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

    显示如何使用ng-repeat& amp;输出表行的代码我的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;
    }
    

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

    包含$ document listener的指令 - 请参阅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);
        }
    }
    

    由于有多少代码,我可能会要求太多人看看这么多代码,但我已经创建了一个插件来展示我已经完成的工作。

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

1 个答案:

答案 0 :(得分:1)

解决了它。这个问题让我想到了我的问题以及必须做些什么:

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

范围。需要$ apply()。我继续把它包装在每个最终修改范围的函数调用周围。

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