问题
I am asking this question because I am not quite clear on how to think of rootscope as a dependency passed to directives
I have a directive that needs to display some information from $rootScope ...
I thought I needed to pass the $rootScope to a directive but when I write a directive like this it seems to work.
.directive("myBar", function () {
return {
restrict: "E",
transclude: true,
replace: true,
template: '<div>' +
'<span ng-transclude></span>' +
'{{rsLabels.welcome}} {{rsUser.firstName}}!' +
'</div>'
}
})
When do I need to do this?
.directive("myBar", function ($rootScope) {
return {
restrict: "E",
transclude: true,
replace: true,
template: '<div>' +
'<span ng-transclude></span>' +
'{{rsLabels.welcome}} {{rsUser.firstName}}!' +
'</div>'
}
})
Can I and HOW do I use rootScope if I need it in the link function of the directive - or should I do it in the controller of the directive?
.directive("myBar", function ($rootScope) {
return {
restrict: "E",
transclude: true,
replace: true,
link: function (scope, element, attrs, rootScope) {
rootScope.rsUser = { firstName: 'Joe' };
rootScope.rsUser = { welcome: 'Welcome' };
},
template: '<div>' +
'<span ng-transclude></span>' +
'{{rsLabels.welcome}} {{rsUser.firstName}}!' +
'</div>'
}
})
My rootScope data is defined in run function
.run(function ($rootScope) {
$rootScope.rsLabels = {
welcome: 'Welcome'
};
$rootScope.rsUser = {
firstName: 'Joe'
};
});
Thank you!
回答1:
From my experiments \ experience, it seems that since all $scopes ultimately inherit from the $rootScope you will be able to access data on it without requesting it as a service, following standard javascript prototypical inheritance rules. If you were to set the scope property in your directive to false or {} you will find that you can no longer access it.
.directive("myBar", function($rootScope) {
return {
restrict: "E",
scope: { /* Isolate scope, no $rootScope access anymore */ },
transclude: true,
replace: true,
template: '<div>' +
'<span ng-transclude></span>' +
'{{rsLabels.welcome}} {{rsUser.firstName}}!' +
'</div>'
};
});
Example: http://jsbin.com/bequy/1/edit
回答2:
You can do this way:
{{$root.rsLabels.welcome}}
回答3:
It's not recommended to use the root scope to set and get properties in your angular application. Try using the $cacheFactory, since that way you can also cache some values over various requests. ($cacheFactory docs)
回答4:
Sometimes I have to use $scope.$root:
app.directive('setOrdinal', function() {
return {
link: function($scope, $element, $attr) {
var steps = $scope.$root.steps;
$scope.$watch(setOrdinal, function(value) {
if (value)
{
// steps code here
}
});
}
};
});
app.controller('stepController', ['$scope', '$rootScope', 'GetSteps', function ($scope, $rootScope, GetSteps) {
var s = $scope;
var r = $rootScope;
s.initialize = function(id)
{
GetSteps.get({id: id}, function(resp){
r.steps = resp.steps;
});
};
}]);
回答5:
After laboring away on this same question for quite some time, I thought it was worth noting something that was neglected in the first post. Here is my original code:
app.directive('countrymap', function()
{
return {
link: function(scope, element, attrs) {
scope.$watch("countryMap", function (newCountry, oldCountry)
{
setTimeout( function()
{
//function body here
}, 100);
})
}
};
}]);
Aside from the more philosophical design question of whether or not you should even use $rootScope at all, there is one blatantly wrong thing with my code above that I feel was left out from Mike's solution - the reference to $rootScope. If you're like me and have segregated your directive and controller files you will need to modify your code as follows:
app.directive('countrymap', ['$rootScope', function($rootScope)
{
return {
link: function(scope, element, attrs) {
$rootScope.$watch("countryMap", function (newCountry, oldCountry)
{
setTimeout( function()
{
//function body here
}, 100);
})
}
};
}]);
Yet, there is still one more nagging question: can I accomplish the same goal without referencing $rootScope in the directive? Indeed you can. You need to broadcast the change to the $rootScope property effectively letting all child scopes know about the change and watching for this change in the directive.
Controller:
$rootScope.countryMap = 'thiscountry_map';
$rootScope.$broadcast( "countryMapChanged", $rootScope.countryMap );
Directive:
app.directive('countrymapalt', [function()
{
return {
link: function(scope, element, attrs) {
scope.$on("countryMapChanged", function(event, map)
{
setTimeout( function()
{
//function body here
}, 100);
})
}
};
}]);
回答6:
Another way is to create a service and throw that service access the $rootScope and other functions. I did it like this because of my environment...
app.service('myService', function ($rootScope)
{
this.removeItem = function (el)
{
console.log('rootScope: ',$rootScope);
return true;
}
});
app.directive('draggable', function($document,myService)
{
return function(scope, element, attr)
{
myService.removeItem({id:1})
}
});
If you can, the best way is Mike solution. if not, try my solution.
来源:https://stackoverflow.com/questions/21736824/angularjs-rootscope-in-directive-link-function