无法从指令访问控制器范围

时间:2012-12-24 14:13:28

标签: javascript angularjs

这是我的应用配置:

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将指令呈现为:

  

你好,未定义

而不是:

  

你好,世界

有什么问题?

4 个答案:

答案 0 :(得分:7)

您正在访问scope[attrs.name],但该指令未提供属性值name

有两个选项:

  1. 将指令更改为elm.text("hello, " + scope['name']); 这不是一种首选方式,因为它硬编码到范围属性名称

  2. 将html更改为<h1 hello name="name"></h1>。这样更好,但我觉得它使用冗余属性

  3. 我建议您将指令更改为elm.text("hello, " + scope[attrs['hello']]);

    甚至更好elm.text("hello, " + scope.$eval(attrs['hello']));

    这样你也可以获得表达式的好处(例如:<h1 hello="name|uppercase"></h1>) 的 demo

    这样html就是<h1 hello="name"></h1>

    关于attrs参数:它只不过是从dom元素上的属性中获取的字符串映射。

答案 1 :(得分:6)

你可以做一些事情,在写这篇文章时,似乎没有在Angular中记录(参见Mark Rajcok在这里的评论:http://docs.angularjs.org/api/ng.$rootScope.Scope)。

从你的指令中:

scope.$parent.name

如果你在指令的console.log(scope)(在指令中)执行scope,你会看到这些属性。

所有这些都说,我不知道这是否是“正确的”Angular约定,因为这个都没有记录,而且我还没有找到关于如何访问控制器的任何其他更好的文档指令就在其中。

答案 2 :(得分:3)

您可以使用scope进行访问。看http://jsfiddle.net/rPUM5/

directives.directive("hello", function () {
    return function (scope, elm, attrs) {
        elm.text("hello, " + scope.name);
    };
});​

答案 3 :(得分:1)

我发现了另一个案例:

如果要访问来自Ajax请求主体的变量,则必须 WAIT直到设置变量

e.g:

# 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