簡體   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