Невозможно получить доступ к области контроллера из директивы
Это мое приложение config:
angular.module('myApp', ['myApp.directives', 'myApp.controllers', 'myApp.services']);
Это мой контроллер:
angular.module('myApp.controllers', [])
.controller('MainCtrl', function ($scope) {
$scope.name = 'world';
});
Это моя директива:
var directives = angular.module('myApp.directives', []);
directives.directive("hello", function () {
return function (scope, elm, attrs) {
elm.text("hello, " + scope[attrs.name]);
};
});
и это мой html:
<div ng-controller="MainCtrl">
<h1 hello></h1>
</div>
Проблема заключается в том, что angular отображает директиву как:
привет, undefined
Вместо:
привет, мир
Что не так?
Ответы
Ответ 1
Вы получаете доступ к scope[attrs.name]
, но директива не предоставляет значение для атрибута name
Есть 2 варианта:
-
Измените директиву на elm.text("hello, " + scope['name']);
Это не является предпочтительным способом, поскольку он жестко кодирует имя свойства области
-
Измените html на <h1 hello name="name"></h1>
. Это лучше, но я чувствую, что использует избыточный атрибут
Я бы предложил изменить директиву на elm.text("hello, " + scope[attrs['hello']]);
Или даже лучше elm.text("hello, " + scope.$eval(attrs['hello']));
таким образом вы получаете преимущество выражений (ex: <h1 hello="name|uppercase"></h1>
)
демонстрация
Таким образом, html будет <h1 hello="name"></h1>
Относительно параметра attrs: это не что иное, как карта строк, взятых из атрибутов, присутствующих в элементе dom.
Ответ 2
Вы можете сделать что-то, что с момента написания этого документа представляется недокументированным в Angular (см. комментарий Марка Райкока здесь: http://docs.angularjs.org/api/ng.$rootScope.Scope).
Из вашей директивы:
scope.$parent.name
Если вы выполняете console.log(scope)
в директиве scope
(изнутри директивы), вы увидите эти свойства.
Все это говорит, я не знаю, является ли это "правильным" соглашением Angular, из-за того, что это и недокументировано, и я не нашел другой лучшей документации о том, как получить доступ к что директива находится внутри.
Ответ 3
Вы можете получить доступ, используя scope
. Посмотрите http://jsfiddle.net/rPUM5/
directives.directive("hello", function () {
return function (scope, elm, attrs) {
elm.text("hello, " + scope.name);
};
});
Ответ 4
Я нашел другой случай:
если вы обращаетесь к переменной, поступающей из тела запроса Ajax, тогда вы должны WAIT, пока не будет установлена переменная.
например:
# in controller
$http.get('/preview').then( (response) ->
$scope.tabs = response.data.tabs
$scope.master_switch = '1'
console.info 'after get response in controller'
)
# in directive
directive('masterSwitch', ->
(scope, element, attrs) ->
alert 'in directive!' # will show before "after get response in controller"
console.info scope.master_switch # is undefined
setTimeout( -> console.info(scope.master_switch), 50) # => 1