链接函数和控制器函数如何在角度指令*享知识?

时间:2022-03-12 19:42:40

I have an angular directive that shows payment history. By default, it shows the last 6 payments using the vm.numberOfPaymentsToDisplay variable. If you click view more, it adds 10. Now, when a user clicks on another section, there's a listener in the link function that is supposed to reset the number to 6, however vm is undefined.

我有一个显示付款历史的角度指令。默认情况下,它使用vm.numberOfPaymentsToDisplay变量显示最后6笔付款。如果你点击查看更多,它会增加10.现在,当用户点击另一个部分时,链接函数中有一个监听器,它应该将数字重置为6,但是vm是未定义的。

Here's the code:

这是代码:

angular.module('nui.settings2.account')
 .directive('paymentHistory', function(){

 function PaymentHistoryController(paymentHistoryService, $filter, $window, $translate){

  const filter = $filter('formatCurrency');

  var vm = this;
  vm.payments = paymentHistoryService.get();
  vm.numberOfPaymentsToDisplay = 6;
  vm.getLastPayment = getLastPayment;
  vm.viewMorePayments = viewMorePayments;
  vm.title = $translate.instant('NUI.SETTINGS.PAYMENT_HISTORY');


  function getLastPayment(){
    const lastTransaction = paymentHistoryService.getLastPayment();
    return lastPaymentInfo = "amount (date)";
  }

  function viewMorePayments(){
    vm.numberOfPaymentsToDisplay = vm.numberOfPaymentsToDisplay + 10;
    return true;
  }
}

function link(scope, element, attrs, [expander, paymentHistory]){
  const containerEl = element.children();
  expander.registerContentContainer(containerEl);
  scope.$on(expander.COLLAPSE_EVENT, () => vm.numberOfPaymentsToDisplay = 6);
  scope.$on("$destroy", () => scope.$emit(expander.CONTAINER_DEREGISTER_EVENT));
  paymentHistory.cancel = () => expander.collapse();
}

return {
  restrict: 'E',
  templateUrl: 'nui/settings2/account/billing/payment-history.directive.html',
  controller: PaymentHistoryController,
  link: link,
  require: ['^^settingExpander', 'paymentHistory'],
  controllerAs: 'PaymentHistoryCtrl',
  bindToController: true
};
});

How can I set vm.numberOfPaymentsToDisplay = 6 in the link function even though this knowledge is only known by the controller?

如何在链接功能中设置vm.numberOfPaymentsToDisplay = 6,即使这些知识只有控制器知道?

2 个解决方案

#1


4  

You can add a method to your PaymentHistoryController like setNumberOfPaymentsToDisplay as you inject your PaymentHistoryController into your link function you can call the method like this:

您可以将一个方法添加到PaymentHistoryController,如setNumberOfPaymentsToDisplay,同时将PaymentHistoryController注入您的链接函数,您可以像这样调用方法:

paymentHistory.setNumberOfPaymentsToDisplay(6);

Controller code:

控制器代码:

function PaymentHistoryController(paymentHistoryService, $filter, $window, $translate){

  const filter = $filter('formatCurrency');

  var vm = this;
  vm.payments = paymentHistoryService.get();
  vm.numberOfPaymentsToDisplay = 6;
  vm.getLastPayment = getLastPayment;
  vm.viewMorePayments = viewMorePayments;
  vm.setNumberOfPaymentsToDisplay = setNumberOfPaymentsToDisplay;
  vm.title = $translate.instant('NUI.SETTINGS.PAYMENT_HISTORY');


  function getLastPayment(){
    const lastTransaction = paymentHistoryService.getLastPayment();
    return lastPaymentInfo = "amount (date)";
  }

  function viewMorePayments(){
    vm.numberOfPaymentsToDisplay = vm.numberOfPaymentsToDisplay + 10;
    return true;
  }

  function setNumberOfPaymentsToDisplay(amount) {
     vm.numberOfPaymentsToDisplay = amount;
  }
}

link code:

链接代码:

function link(scope, element, attrs, [expander, paymentHistory]){
  const containerEl = element.children();
  expander.registerContentContainer(containerEl);
  scope.$on(expander.COLLAPSE_EVENT, () => paymentHistory.setNumberOfPaymentsToDisplay(6));
  scope.$on("$destroy", () => scope.$emit(expander.CONTAINER_DEREGISTER_EVENT));
  paymentHistory.cancel = () => expander.collapse();
}

#2


1  

Actually you have more options. the general approach to share data between components is to use a service that is a singleton , a single instance cached and injected by angular everytime you use it inside your component. another valid solution is to emit events.

其实你有更多的选择。在组件之间共享数据的一般方法是使用单个服务,单个实例缓存并在每次在组件内部使用时按角度注入。另一个有效的解决方案是发出事件。

Service:

服务:

.service('MyService', function(){
 var data;
 this.setData = function(newData){
   data = newData;
 }
 this.getData = function(){
  return data;
 }
})

Events:

事件:

$rootScope.$broadcast('my.evt', data); //down in the scope chain, visible to any scope
$rootScope.$emit('my.evt', data); //up in the scope chain since is the rootscope only visible to rootScope

$scope.$emit //up in the scope chain
$scope.$broacast //down in the scope chain

to listen for events:

听取事件:

$rootScope.$on('my.evt', function(evt, data){ //do something }

or

要么

$scope.$on('my.evt', function(evt, data){ //do something }

However in this case you're using the link function to modify your business logic and this is not the the conventional approach, usually the link is used only to handle dom events and to modify the dom. so my personal advice is to refactor your code and put the whole business logic inside the controller

但是在这种情况下,您使用链接功能来修改业务逻辑,这不是传统方法,通常链接仅用于处理dom事件和修改dom。所以我个人的建议是重构代码并将整个业务逻辑放在控制器中

#1


4  

You can add a method to your PaymentHistoryController like setNumberOfPaymentsToDisplay as you inject your PaymentHistoryController into your link function you can call the method like this:

您可以将一个方法添加到PaymentHistoryController,如setNumberOfPaymentsToDisplay,同时将PaymentHistoryController注入您的链接函数,您可以像这样调用方法:

paymentHistory.setNumberOfPaymentsToDisplay(6);

Controller code:

控制器代码:

function PaymentHistoryController(paymentHistoryService, $filter, $window, $translate){

  const filter = $filter('formatCurrency');

  var vm = this;
  vm.payments = paymentHistoryService.get();
  vm.numberOfPaymentsToDisplay = 6;
  vm.getLastPayment = getLastPayment;
  vm.viewMorePayments = viewMorePayments;
  vm.setNumberOfPaymentsToDisplay = setNumberOfPaymentsToDisplay;
  vm.title = $translate.instant('NUI.SETTINGS.PAYMENT_HISTORY');


  function getLastPayment(){
    const lastTransaction = paymentHistoryService.getLastPayment();
    return lastPaymentInfo = "amount (date)";
  }

  function viewMorePayments(){
    vm.numberOfPaymentsToDisplay = vm.numberOfPaymentsToDisplay + 10;
    return true;
  }

  function setNumberOfPaymentsToDisplay(amount) {
     vm.numberOfPaymentsToDisplay = amount;
  }
}

link code:

链接代码:

function link(scope, element, attrs, [expander, paymentHistory]){
  const containerEl = element.children();
  expander.registerContentContainer(containerEl);
  scope.$on(expander.COLLAPSE_EVENT, () => paymentHistory.setNumberOfPaymentsToDisplay(6));
  scope.$on("$destroy", () => scope.$emit(expander.CONTAINER_DEREGISTER_EVENT));
  paymentHistory.cancel = () => expander.collapse();
}

#2


1  

Actually you have more options. the general approach to share data between components is to use a service that is a singleton , a single instance cached and injected by angular everytime you use it inside your component. another valid solution is to emit events.

其实你有更多的选择。在组件之间共享数据的一般方法是使用单个服务,单个实例缓存并在每次在组件内部使用时按角度注入。另一个有效的解决方案是发出事件。

Service:

服务:

.service('MyService', function(){
 var data;
 this.setData = function(newData){
   data = newData;
 }
 this.getData = function(){
  return data;
 }
})

Events:

事件:

$rootScope.$broadcast('my.evt', data); //down in the scope chain, visible to any scope
$rootScope.$emit('my.evt', data); //up in the scope chain since is the rootscope only visible to rootScope

$scope.$emit //up in the scope chain
$scope.$broacast //down in the scope chain

to listen for events:

听取事件:

$rootScope.$on('my.evt', function(evt, data){ //do something }

or

要么

$scope.$on('my.evt', function(evt, data){ //do something }

However in this case you're using the link function to modify your business logic and this is not the the conventional approach, usually the link is used only to handle dom events and to modify the dom. so my personal advice is to refactor your code and put the whole business logic inside the controller

但是在这种情况下,您使用链接功能来修改业务逻辑,这不是传统方法,通常链接仅用于处理dom事件和修改dom。所以我个人的建议是重构代码并将整个业务逻辑放在控制器中