2017-05-26 39 views
1

我有一个指令设置是这样的:angularjs bindToController不能调用方法

angular.module('widget.directives').directive('applePay', applePay); 

function applePay() { 
    return { 
     restrict: 'A', 
     controller: 'ApplePayController', 
     controllerAs: 'controller', 
     scope: { 
      onCheckComplete: '&applePay' 
     }, 
     bindToController: true, 
     templateUrl: 'app/directives/apple-pay/apple-pay.html', 
     link: function (scope, element, attrs, controller) { 
      element.find('button').bind('click', controller.checkout); 
     } 
    }; 
}; 

而且它的控制器是这样的:

angular.module('widget.directives').controller('ApplePayController', applePayController); 

applePayController.$inject = ['applePayService']; 

function applePayController(applePayService) { 
    var self = this; 

    // Method binding 
    self.checkout = checkout; 

    init(); 

    ////////////////////////////////////////////////// 

    function init() { 
     applePayService.checkAvailability(setAvailability); 
    }; 

    function setAvailability(available) { 
     self.available = available === true; 
     console.log(self); 
     self.onCheckComplete({ available: self.available }); 
    }; 

    function checkout(e) { 
     applePayService.checkout(e, onComplete, onError); 
    }; 

    function onComplete(result, completion) { 
     console.log(result, completion); 
    }; 

    function onError(error) { 
     self.error = error; 
    }; 
}; 

我的这个网站是这样的:

<div apple-pay="controller.applePayAvailable(available)"></div> 

当指令加载时出现错误:

TypeError: self.onCheckComplete is not a function

有谁知道为什么? 我有一个类似的指令,工作正常。

+0

在函数'setAvailability'中调用了这个函数'self.onCheckComplete({available:self.available});'但它看起来并没有在控制器里面定义 – quirimmo

+0

不,实际上我已经知道了。这是因为在将范围绑定到控制器之前,在控制器中调用init。我不得不将init方法添加到链接方法 – r3plica

+0

这不是1.6中推荐的方法。 – TSmith

回答

0

这是因为控制器有控制器实例化时调用的init方法。问题在于范围还没有受到约束。所以我必须将控制器更改为:

angular.module('widget.directives').controller('ApplePayController', applePayController); 

applePayController.$inject = ['applePayService']; 

function applePayController(applePayService) { 
    var self = this; 

    // Method binding 
    self.init = init; 
    self.checkout = checkout; 

    ////////////////////////////////////////////////// 

    function init() { 
     applePayService.checkAvailability(setAvailability); 
    }; 

    function setAvailability(available) { 
     self.available = available === true; 
     console.log(self); 
     self.onCheckComplete({ available: self.available }); 
    }; 

    function checkout(e) { 
     applePayService.checkout(e, onComplete, onError); 
    }; 

    function onComplete(result, completion) { 
     console.log(result, completion); 
    }; 

    function onError(error) { 
     self.error = error; 
    }; 
}; 

然后将init方法添加到指令的链接函数中。

angular.module('widget.directives').directive('applePay', applePay); 

function applePay() { 
    return { 
     restrict: 'A', 
     templateUrl: 'app/directives/apple-pay/apple-pay.html', 
     controller: 'ApplePayController', 
     controllerAs: 'controller', 
     bindToController: true, 
     scope: { 
      onCheckComplete: '&applePay' 
     }, 
     link: function (scope, element, attrs, controller) { 
      element.find('button').bind('click', controller.checkout); 
      controller.init(); 
     } 
    }; 
}; 

从上方加入init方法作为控制器上的公共方法,然后调用从指令controller.init()之间的唯一区别。这确保了范围在启动之前受到约束。

+0

这看起来很奇怪。你使用的是什么版本的angularJS? – TSmith

+0

1.6.4但我不认为这很奇怪,它是消化循环的工作方式。控制器在指令之前被实例化,因此范围在该点不可用。 – r3plica

0

我发现这很奇怪,因为我有一些1.5x代码在做同样的事情没有问题。在学习1.6x后,我做了一些深入的了解,了解发生了什么。影响这里事物的变化是一个名为preAssignBindingsEnabled的房产。这个突破变化记录在gitHub post。这也是迁移document here

在迁移文档的一部分,还有很大的代码片段,我想你会发现你的情况有所帮助,让您保持您的link()功能都是关于DOM操作,而不是担心调用到控制器。在迁移文档的Core:Services - > $ compile部分下,它使用1.5x $onInit()钩子语法显示一条带有控制器声明的指令,以确保绑定在控制器初始化之前存在。

我适应这您的情况:

function applePayController(applePayService) { 
    var self = this; 

    // Method binding 
    self.checkout = checkout; 

    //**Hook below to ensure bindings are set when preAssignBindingsEnabled is 
    //false (default setting with 1.6x**) 

    self.$onInit = init; 

    //init(); 

    function init() { 
    applePayService.checkAvailability(setAvailability); 
    }; 

    . 
    . 
    . 
}; 

一旦绑定所有的设置,控制器的$的OnInit它将自动被称为角,并且功能正常执行。希望这提供了一些额外的选择!

相关问题