如何将控制器数据传递给AngularJS中的自定义指令?

时间:2018-07-26 20:23:59

标签: javascript angularjs angularjs-directive

我在AngularJS中有一个自定义指令,我想从控制器中将变量传递给它。

控制器:

angular.
    module('orderOverview').
    component('orderOverview', {
        templateUrl: 'home-page/order-overview/order-overview.template.html',
        controller: ['Orders',
            function ControllerFunction(Orders) {
        var self = this;

        // Order Info
        Orders.getOverview().$promise.then(function(data) {
          self.LineItems = data;
        });
        // Order Info
      }
    ]
  });

指令

angular.
    module('myApp').
    directive('gvInitializeOrderStatus', function() {
    return {
      scope: {
        field: '@',
        myData: '='
      },
      link: function(scope, element) {
        console.log('field:', scope.field);
        console.log('data:', scope.myData);
      }
    }
    });

HTML

<div gv-initialize-order-status field="InquiryDone" myData="$ctrl.LineItems">
    <span class="tooltiptext">Inquiry</span>
</div>

加载页面时,field正常运行,但是data未定义。

我已经尝试了很多方法,但是如果它让您对我的想法有所了解,这就是我应该想到的方法。

在同一模板的另一点上,我将ng-repeat数据传递给指令很好,但是在这种情况下,我特别不想ng-repeat

ng-repeat HTML成功传递了数据

<li ng-repeat="lineItem in $ctrl.LineItems">
    <div class="status-circle" 
         ng-click="toggleCircle($event, lineItem, 'InquiryDone')"
         field="InquiryDone" item="lineItem" gv-initialize-statuses>
        <span class="tooltiptext">Inquiry</span>
    </div>
</li>

在另一个指令gv-initialize-statuses中,我在scope对象中使用了相同的概念,并且具有类似scope: { 'field': '=' }的名称,并且效果很好。

如何在不使用ng-repeat的情况下完成此操作?

5 个答案:

答案 0 :(得分:1)

应避免与=进行双向绑定

该指令需要在链接函数中使用$ watch:

app.directive('gvInitializeOrderStatus', function() {
    return {
      scope: {
        field: '@',
        ̶m̶y̶D̶a̶t̶a̶:̶ ̶'̶=̶'̶
        myData: '<'
      },
      link: function(scope, element) {
        console.log('field:', scope.field);
        console.log('data:', scope.myData);
        scope.$watch('myData', function(value) {
            console.log('data:', scope.myData);
        });
      }
    }
});

诸如ng-repeat之类的指令会自动使用观察者。

出于性能原因,也应避免与=进行双向绑定。与<的单向绑定更有效。


要获得更有效的代码,请在控制器中使用$onChanges life-cycle hook

app.directive('gvInitializeOrderStatus', function() {
    return {
      scope: {
        field: '@',
        ̶m̶y̶D̶a̶t̶a̶:̶ ̶'̶=̶'̶
        myData: '<'
      },
      bindToController: true,
      controllerAs: "$ctrl",
      controller: function() {
        console.log('field:', this.field);
        console.log('data:', this.myData);
        this.$onChanges = function(changes) {
            if (changes.myData)
                console.log('data:', changes.myData.currentValue);
            };
        });
      }
    }
});

这样做将使代码更高效,并且更容易迁移到Angular 2 +。


手表有不同级别:

ng-repeat指令实际上使用了$watchCollection

该指令可能需要使用$doCheck Life-Cycle hook

有关更多信息,请参见

答案 1 :(得分:0)

如果您只想要指令中的数据,请执行此操作

Orders.getOverview().$promise.then(function(data) {
          self.LineItems = data;
          $rootScope.$broadcast('myData', data);
        });

在您的指令中,只需使用回调函数捕获此事件

$scope.$on('myData', function(event, args) {

    var anyThing = args;
    // do what you want to do
});

答案 2 :(得分:0)

问题出在$promise

指令激活时,

self.LineItems尚未就绪。这就是为什么数据是undefined

也许ng-if可以帮助您:

<div ng-if="$ctrl.LineItems" gv-initialize-order-status field="InquiryDone" myData="$ctrl.LineItems">
    <span class="tooltiptext">Inquiry</span>
</div>

希望这会有所帮助。祝你好运!

答案 3 :(得分:0)

因此,当我在文档中阅读有关$ compile的信息时,我找到了一个有效的答案。我意识到您可以获取插值的属性值,因此我从范围对象中删除了myData字段,而是通过attrs对象访问了该值,就像这样。

指令

angular.
    module('myApp').
    directive('gvInitializeOrderStatus', function() {
    return {
      scope: {
        field: '@'
      },
      link: function(scope, element, attrs) {
        console.log('field:', scope.field);
        console.log('attrs:', attrs);
        attrs.$observe('lineItems', function(value) {
          console.log(value);
        })
      }
    }
    });

HTML

<div gv-initialize-order-status field="InquiryDone" lineItems="{{$ctrl.LineItems}}">
     <span class="tooltiptext">Inquiry</span>
</div>

请注意将添加的{{ }}添加到lineItems属性。 attrs.$observe块也使我可以知道该值的更改。

答案 4 :(得分:-1)

在指令中

angular.
module('myApp').
directive('gvInitializeOrderStatus', function() {
return {
  scope: {
    field: '@',
    ngModel: '='     // <- access data with this (ngModel to ng-model in view)
  },
  link: function(scope, element) {
    console.log('field:', scope.field);
    console.log('data:', scope.ngModel);
  }
}
});

可见

<div gv-initialize-order-status field="InquiryDone" ng-model="$ctrl.LineItems">
  <span class="tooltiptext">Inquiry</span>
</div>