通过指令中的属性传递数据以在编译阶段访问它?

时间:2015-07-07 13:30:43

标签: angularjs angularjs-directive

有没有办法在编译阶段访问指令中的对象。因为编译阶段不提供范围。和attrs.data将返回一个字符串,这是获取数据的最佳方式。

**

<body ng-controller="MainCtrl">
        <h2>MainCtrl</h2>
        {{data}}

        <div dir data="data.items">
        </div>
      </body>

**

angular.module('app', [])
.controller('MainCtrl', function($scope) {
  $scope.data = {
    items: [{
      id: 1,
      name: "first"
    }, {
      id: 2,
      name: "second"
    }, {
      id: 3,
      name: "third" 
    }]
  }
})

.directive('dir', function() {
  return {

    replace: true,
    restrict: 'A', 
    compile: function(element, attrs) {
              //need to access $scope.data defined in MainCtrl.
      });
    }

  }
})

3 个答案:

答案 0 :(得分:0)

隔离范围是绑定父范围

数据的好模式
<div dir data="data.items">

并将其提供给指令的linkcontroller,就像那样

angular.module('app').directive('dir', function() {
  return {
    scope: {
      data: '='
    },
    ...
  }
})

或者您可以使用单向绑定

<div dir data="{{data.items}}">

link函数attrs.data中获取它。这就是Angular期望它完成的方式。

您的问题本身描述了编译阶段发生的事情。您无法访问范围,

<div dir data="{{data.items}}">

也无济于事,因为attrs中的属性未在compile函数中进行插值。这就是为什么它不能那样工作的原因:MainCtrl在指令的compile之后运行

答案 1 :(得分:0)

渲染过程分为编译和链接阶段是角度框架的基石。这种结构意味着您可以在模板实例化之前有机会摆弄模板&#39;在链接阶段使用范围数据。

指令的编译回调只运行一次 - 而链接回调可能会以不同的范围运行任意次。

那么,如果要传递给angular的模板取决于应用程序中的某些数据,该怎么办?一旦你的指令注册了angular,它的模板就是不可变的。

我们无法使用范围 - 所以我所做的就是拥有一个javascript对象 - 让它称之为注册表 - 它位于角度上下文之外。然后,我将需要访问的数据从编译阶段放入注册表,并通过模板中的属性将密钥传递到编译阶段,您可以在编译阶段访问该模板。

使用此方法时,需要注意不要泄漏内存。可能通过使用$ destroy回调清除相应的注册表项。

答案 2 :(得分:-1)

让我们可以访问compile

scope
angular.module('app', [])
  .controller('app', function($scope) {
    this.data = {
      items: [{
        id: 1,
        name: "first"
      }, {
        id: 2,
        name: "second"
      }, {
        id: 3,
        name: "third"
      }]
    }
  })
  .directive('dir', function() {
    return {
      replace: true,
      restrict: 'A',
      scope: {
        data: '='
      },
      compile: function(element) {
        setTimeout(function() {
          alert(JSON.stringify(element.scope().ctrl.data))
        }, 1)
      }
    }
  })

angular.bootstrap(document.body, ['app'])