繁体   English   中英

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

[英]How to pass controller data to a custom directive in AngularJS?

我在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来完成此操作?

应避免与=双向绑定

该指令需要在链接函数中使用$ 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生命周期挂钩

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

有关更多信息,请参见

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

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
});

问题是$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>

希望这可以帮助。 祝好运!

因此,当我在文档中阅读有关$ 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块也使我可以知道该值的更改。

在指令中

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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM