[英]AngularJS $watch only firing on intitialize
我有一个使用d3来显示项目的有角度的应用程序,并且有一个infoPanel来显示单击的项目的信息。 这是有效的,但是单击该项目以激活/打开信息面板不起作用。
在d3数据控制文件中,我有:
'use strict';
var settings ;
angular.module('App')
.directive('data', ['sessionmgmt', 'thedata', 'gui', function (session, data, gui) {
return {
link: function postLink(scope, element, attrs) {
var promise = angular....getData...;
promise.then(function () {
settings = session.settings;
svg = ...
createItems(svg, items);
}, function () {});
}
};
}]);
function createItems(svg, items) {
let item = svg.append("g")
.attr("class", "nodes")
.selectAll(".node")
.data(items, function (d) {
return d.id;
});
appendIcons(item);
}
function appendIcons(nodes){
nodes = nodes.enter().append("g")
.attr("class", "node");
nodes.append("title")
.text(function (d) {
return d.data['label'];
});
nodes.on("click",function(d){
if(settings.selectedItem === d.id){
settings.selectedItem = null;
}else{
settings.selectedItem = d.id;
}
});
}
然后在我的infoPanel控制器中,我有:
'use strict';
angular.module('App')
.controller('ContentpanelCtrl', ['$scope', 'sessionmgmt', function ($scope, sessionmgmt) {
var contentPanel = this;
this.settings = sessionmgmt.settings;
$scope.activate = function activate() {
contentPanel.settings.contentPanelOpen = true;
};
$scope.getSelected = function getSelected(){
return contentPanel.settings.itemSelected;
}
$scope.isNodeSelected = function isSelected(){
return contentPanel.settings.itemSelected !== null;
}
$scope.$watch("contentPanel.settings.itemSelected", function(newVal, oldVal) {
console.log(newVal);
if (newVal !== oldVal){
$scope.activate();
}
});
}]);
首次加载页面时,console.log正在运行,但是当我单击这些项目时,不会触发该手表。 我知道“点击”有效,因为getSelected在我的信息面板上显示了正确的数据。 'watch'和getSelected都使用完全相同的设置变量。
有两种方法可以做到这一点。 第一个是我在注释中建议的内容,在该注释中,您将指令的范围作为参数appendIcons
给调用scope.$apply();
的createItems
和appendIcons
函数scope.$apply();
在点击事件中。
从指令:
createItems(svg, items, scope);
以及其他功能:
function createItems(svg, items, scope) {
let item = svg.append("g")
/* ... */
appendIcons(item, scope);
}
function appendIcons(nodes, scope){
nodes = nodes.enter().append("g")
/* ... */
nodes.on("click",function(d){
if(settings.selectedItem === d.id){
settings.selectedItem = null;
}else{
settings.selectedItem = d.id;
}
scope.$apply();
});
}
另一种方法是更改$scope.$watch()
函数。 您要注意的contentPanel.settings.itemSelected
不在范围内,因为您正在使用this
而不是$scope
(我假定是controllerAs
一部分)。 为了使手表正常工作,您需要使用一个函数作为手表函数中的第一个参数,如下所示:
$scope.$watch(function(){
return contentPanel.settings.itemSelected;
}, function(newVal, oldVal) {
if (newVal !== oldVal){
$scope.activate();
}
});
也许您可以尝试将确切的对象而不是字符串传递给观察器?
$scope.$watch(function() {
if (contentPanel && contentPanel.settings) {
return contentPanel.settings.itemSelected;
}
}, function(newVal, oldVal) {
console.log(newVal);
if (newVal !== oldVal){
$scope.activate();
}
});
作为我的评论的补充。
在控制器中:
$scope.toggleSelectedItem = function(item) {
if(contentPanel.settings.itemSelected &&
contentPanel.settings.itemSelected === item.id){
contentPanel.settings.itemSelected = null;
}
else {
contentPanel.settings.itemSelected = item.id;
}
}
HTML:
<div ng-repeat="item in items" ng-click="toggleSelectedItem(item)">
<!--Content-->
</div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.