Невозможно получить доступ к области контроллера из директивы

Это мое приложение 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