如何在此处重新调整我的指令以在 2 个不同的范围内工作?
How to repurpose my directive here to work in 2 different scopes?
http://plnkr.co/edit/39FGMocKB5GtQWnI1TFw?p=preview
我有 sidebar,其中包含标签列表,当您单击标签时,我使用 TagDetailsFactory
将标签发送到 [= 的范围内36=]视图控制器。
除了将鼠标悬停在 TagDetailsFactory 范围内的标记上之外,一切都很好。
tagDetails
模板不会显示,但是如果您将鼠标悬停在侧边栏范围内的同一标签上,tagDetails
会在两者中显示。这是错误的。
将鼠标悬停在边栏中的标签上应该只显示该标签的标签详细信息,以及视图范围内的标签的详细信息。
将鼠标悬停在视图范围内的标签上,不显示其详细信息
将鼠标悬停在侧边栏范围内的标签上,应该只显示其标签的详细信息,而不是视图范围内的标签,就像这里所做的那样:
步骤:
- 第一个标签数组在 cnt 控制器中
- 当您点击标签时,它会存储在 TagDetailsFactory 服务中
- 然后我向视图控制器广播一个事件,然后调用 TagDetailsFactory 中的 getTagDetails 函数来检索保存的标签并将它们存储到视图控制器中的 viewTags 数组中。
// Code goes here
angular.module('app', [])
.directive('tagDetails', function() {
return {
restrict: "E",
link: function($scope, el, attrs) {
// console.debug($scope, attrs);
},
scope:{
tag:'='
},
template: '<div ng-show="tag.showDetails">{{tag.details}}</div>'
};
})
.factory('TagDetailsFactory', function() {
var savedTags = [];
var saveTagDetails = function(tag) {
savedTags.push(tag);
}
var getTagDetails = function() {
return savedTags;
}
return {
saveTagDetails : saveTagDetails,
getTagDetails : getTagDetails
};
})
.controller('sidebar', function($scope,
$rootScope,
TagDetailsFactory) {
$scope.tags = [];
for(var i = 0; i < 10; i++) {
$scope.tags.push(
{ name: 'Foo Bar ' + i, details: 'Details' + i }
);
}
$scope.showTagDetails = function(t) {
t.showDetails = true;
}
$scope.leaveTag = function(t) {
t.showDetails = false;
}
$scope.sendTag = function(t) {
TagDetailsFactory.saveTagDetails(t);
$rootScope.$broadcast('updateView');
}
})
.controller('view', function($scope,
$rootScope,
TagDetailsFactory) {
$scope.viewTags = [];
$scope.$on('updateView', function() {
$scope.viewTags = TagDetailsFactory.getTagDetails();
});
$scope.showTagDetails = function(v) {
v.showDetails = true;
}
$scope.leaveTag = function(v) {
v.showDetails = false;
}
});
我必须在这里创建第二个指令吗?成为视图范围内标签详细信息的模板?或者我当前的 tagDetails
指令可以以某种方式以 Angular 的方式重新调整用途吗?
我将你的 Plunker 与一个工作副本进行了分叉,我将解释我所做的更改。
这里的代码有两个问题。第一个是一个简单的拼写错误,导致您的 header 没有为鼠标悬停引用正确的函数。您的函数正在调用 showTagDetailsView(v)
和 leaveTagView(v)
,但它们在控制器上被命名为 showTagDetails
和 leaveTag
。
第二个问题是将项目添加到 savedTags[]
的方式。在 JavaScript 中,object 是通过引用传递的。当您调用 savedTags.push(tag);
时,您正在将对同一 object 的引用推送到新数组中。对一个数组中的 object 所做的任何更改都将反映在另一个数组中。
相反,您想要的是 savedTags[]
中 object 的单独副本。这可以通过使用 angular.copy
来完成。请注意,我在制作副本之前还重置了 tag.showDetails = false;
,否则新副本会将其设置为 true,即使您在单击时将鼠标悬停在其他元素上,详细信息也会在副本出现时立即显示它。
var saveTagDetails = function(tag) {
tag.showDetails = false;
savedTags.push(angular.copy(tag));
}
附带说明一下,您可能还对此处的 CSS 有疑问,因为悬停似乎会改变列表的位置,并且在某些情况下,悬停实际上会导致标签自行移出悬停,造成弹跳效果。
http://plnkr.co/edit/39FGMocKB5GtQWnI1TFw?p=preview
我有 sidebar,其中包含标签列表,当您单击标签时,我使用 TagDetailsFactory
将标签发送到 [= 的范围内36=]视图控制器。
除了将鼠标悬停在 TagDetailsFactory 范围内的标记上之外,一切都很好。
tagDetails
模板不会显示,但是如果您将鼠标悬停在侧边栏范围内的同一标签上,tagDetails
会在两者中显示。这是错误的。
将鼠标悬停在边栏中的标签上应该只显示该标签的标签详细信息,以及视图范围内的标签的详细信息。
将鼠标悬停在视图范围内的标签上,不显示其详细信息
将鼠标悬停在侧边栏范围内的标签上,应该只显示其标签的详细信息,而不是视图范围内的标签,就像这里所做的那样:
步骤:
- 第一个标签数组在 cnt 控制器中
- 当您点击标签时,它会存储在 TagDetailsFactory 服务中
- 然后我向视图控制器广播一个事件,然后调用 TagDetailsFactory 中的 getTagDetails 函数来检索保存的标签并将它们存储到视图控制器中的 viewTags 数组中。
// Code goes here
angular.module('app', [])
.directive('tagDetails', function() {
return {
restrict: "E",
link: function($scope, el, attrs) {
// console.debug($scope, attrs);
},
scope:{
tag:'='
},
template: '<div ng-show="tag.showDetails">{{tag.details}}</div>'
};
})
.factory('TagDetailsFactory', function() {
var savedTags = [];
var saveTagDetails = function(tag) {
savedTags.push(tag);
}
var getTagDetails = function() {
return savedTags;
}
return {
saveTagDetails : saveTagDetails,
getTagDetails : getTagDetails
};
})
.controller('sidebar', function($scope,
$rootScope,
TagDetailsFactory) {
$scope.tags = [];
for(var i = 0; i < 10; i++) {
$scope.tags.push(
{ name: 'Foo Bar ' + i, details: 'Details' + i }
);
}
$scope.showTagDetails = function(t) {
t.showDetails = true;
}
$scope.leaveTag = function(t) {
t.showDetails = false;
}
$scope.sendTag = function(t) {
TagDetailsFactory.saveTagDetails(t);
$rootScope.$broadcast('updateView');
}
})
.controller('view', function($scope,
$rootScope,
TagDetailsFactory) {
$scope.viewTags = [];
$scope.$on('updateView', function() {
$scope.viewTags = TagDetailsFactory.getTagDetails();
});
$scope.showTagDetails = function(v) {
v.showDetails = true;
}
$scope.leaveTag = function(v) {
v.showDetails = false;
}
});
我必须在这里创建第二个指令吗?成为视图范围内标签详细信息的模板?或者我当前的 tagDetails
指令可以以某种方式以 Angular 的方式重新调整用途吗?
我将你的 Plunker 与一个工作副本进行了分叉,我将解释我所做的更改。
这里的代码有两个问题。第一个是一个简单的拼写错误,导致您的 header 没有为鼠标悬停引用正确的函数。您的函数正在调用 showTagDetailsView(v)
和 leaveTagView(v)
,但它们在控制器上被命名为 showTagDetails
和 leaveTag
。
第二个问题是将项目添加到 savedTags[]
的方式。在 JavaScript 中,object 是通过引用传递的。当您调用 savedTags.push(tag);
时,您正在将对同一 object 的引用推送到新数组中。对一个数组中的 object 所做的任何更改都将反映在另一个数组中。
相反,您想要的是 savedTags[]
中 object 的单独副本。这可以通过使用 angular.copy
来完成。请注意,我在制作副本之前还重置了 tag.showDetails = false;
,否则新副本会将其设置为 true,即使您在单击时将鼠标悬停在其他元素上,详细信息也会在副本出现时立即显示它。
var saveTagDetails = function(tag) {
tag.showDetails = false;
savedTags.push(angular.copy(tag));
}
附带说明一下,您可能还对此处的 CSS 有疑问,因为悬停似乎会改变列表的位置,并且在某些情况下,悬停实际上会导致标签自行移出悬停,造成弹跳效果。