AngularJS 多个指令的范围问题
AngularJS scoping issue with multiple directives
我正在为名为 trNgGrid 的网格实现添加一些键盘导航支持。我有一些代码在工作,但我认为范围界定问题是胜利与失败之间的问题。
我想要达到的目标:
- 鼠标悬停时,将网格项标记为 "activated" 并添加 "active" class
- 在 up/down/left/right 箭头键上 select 下一个网格行 - 应用 "activated" 状态并对其激活 class。
我已经实现了 mousedown 功能,并且运行良好。在初始化时,我有一个名为 gridOptions.selectedIndex 的选项,默认为 0。此选项在主父指令中定义 - 请参阅 plnkr trNgGrid.js line 945
selectedIndex: '=?' //not sure why the ? really - just mimicking others in this grid directive
鼠标悬停时,将调用一个函数,将 gridOptions.selectedIndex 设置为鼠标悬停行的索引。如果 $index==gridOptions.selectedIndex.
,每一行都有一个 ng-class 应用设置活动 class
显示如何使用 ng-repeat 和我的 ng-class 设置输出 table 行的代码 - 请参阅 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 侦听器(只要页面上有网格,我就需要侦听箭头键 - 永远不会超过一个网格一次在页面上)。对于每个与正确的键代码匹配的按键,我调用一个函数来适当地更新 gridOptions.selectedIndex。基于 ng-class 属性(活动:$index==gridOptions.selectedIndex),理论上应该将 "active" class 和 css 样式应用到该行。然而,这并没有发生。我试图以与鼠标悬停功能相同的方式引用 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;
}
});
}
};
}
};
}
])
具有 up/down/left/right/arrow 逻辑的控制器功能 - 请参阅 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 来展示我所做的事情。
解决了。这个问题让我了解了我的问题以及必须要做的事情:
How do I update an angularjs page after a scope update?
scope.$apply() 是必需的。我继续将它包装在每个最终修改范围的函数调用中。
scope.$apply(function(){
scope.navigateRows("up");
});
我正在为名为 trNgGrid 的网格实现添加一些键盘导航支持。我有一些代码在工作,但我认为范围界定问题是胜利与失败之间的问题。
我想要达到的目标:
- 鼠标悬停时,将网格项标记为 "activated" 并添加 "active" class
- 在 up/down/left/right 箭头键上 select 下一个网格行 - 应用 "activated" 状态并对其激活 class。
我已经实现了 mousedown 功能,并且运行良好。在初始化时,我有一个名为 gridOptions.selectedIndex 的选项,默认为 0。此选项在主父指令中定义 - 请参阅 plnkr trNgGrid.js line 945
selectedIndex: '=?' //not sure why the ? really - just mimicking others in this grid directive
鼠标悬停时,将调用一个函数,将 gridOptions.selectedIndex 设置为鼠标悬停行的索引。如果 $index==gridOptions.selectedIndex.
,每一行都有一个 ng-class 应用设置活动 class显示如何使用 ng-repeat 和我的 ng-class 设置输出 table 行的代码 - 请参阅 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 侦听器(只要页面上有网格,我就需要侦听箭头键 - 永远不会超过一个网格一次在页面上)。对于每个与正确的键代码匹配的按键,我调用一个函数来适当地更新 gridOptions.selectedIndex。基于 ng-class 属性(活动:$index==gridOptions.selectedIndex),理论上应该将 "active" class 和 css 样式应用到该行。然而,这并没有发生。我试图以与鼠标悬停功能相同的方式引用 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;
}
});
}
};
}
};
}
])
具有 up/down/left/right/arrow 逻辑的控制器功能 - 请参阅 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 来展示我所做的事情。
解决了。这个问题让我了解了我的问题以及必须要做的事情:
How do I update an angularjs page after a scope update?
scope.$apply() 是必需的。我继续将它包装在每个最终修改范围的函数调用中。
scope.$apply(function(){
scope.navigateRows("up");
});