I have 3 nested directives:
ExchangeWidget -> CoinInput (2 total) -> Coin (Several)
The code:
ExchangeWidgetDirective
'use strict';
import cointInputTpl from './exchangewidget.html';
function exchangeWidgetComponenet($log) {
'ngInject';
var directive = {
restrict: 'E',
templateUrl: cointInputTpl,
controller: exchangeWidgetController,
controllerAs: 'vm',
bindToController: true,
scope: {
amount: '@',
type: '@',
address: '=',
postSelect: '=',
changeCounterPrice: '='
}
};
return directive;
function exchangeWidgetController ($scope, CHANGED_EVENT_SUFFIX) {
'ngInject';
let self = this;
self.postSelect = function (newCoin, prevCoin, type) {
// TODO: migrate to conf
type = type === 'deposit' ? 'receive' : 'deposit';
let eventData = {
newCoin: newCoin,
prevCoin: prevCoin,
};
let event = 'reset' + type;
$scope.$broadcast(event, eventData);
};
self.changeCounterPrice = function (eventData) {
let eventName = eventData.type + CHANGED_EVENT_SUFFIX;
$scope.$broadcast(eventName, eventData);
};
self.showWithdrawAddress = function () {
$scope.$parent.showWithdrawAddress = true;
}
}
}
export default exchangeWidgetComponenet;
CointInputDirective
'use strict';
import cointInputTpl from './coininput.html';
import _ from 'lodash/core';
function coinInputComponenet($log) {
'ngInject';
var directive = {
restrict: 'E',
templateUrl: cointInputTpl,
controller: coinInputController,
controllerAs: 'vm',
bindToController: true,
scope: {
amount: '@',
type: '@',
selectedCoin: '@',
showWithdrawAddress: '@',
postSelect: '=',
changeCounterPrice: '='
}
};
return directive;
function coinInputController ($scope, $element, $attrs,
Price, AMOUNT_CHANGE_DEBOUNCE, CHANGED_EVENT_SUFFIX) {
'ngInject';
let self = this;
let hideCounterEvent = 'reset' + this.type;
// TODO: refactor to configs
let counterChangedEvent = this.type === 'deposit' ? 'receive' + CHANGED_EVENT_SUFFIX : 'deposit' + CHANGED_EVENT_SUFFIX;
$log.debug('Hello from coinInput controller!');
self.icons = [
{name: 'BTC'},
{name: 'LTC'},
{name: 'ETH'}
];
self.select = function (coinName) {
let prevCoin = self.selectedCoin;
self.selectedCoin = coinName;
self.postSelect(coinName, prevCoin, self.type);
$scope.$broadcast('reset')
};
$scope.$on(hideCounterEvent, function(event, eventData) {
if (eventData.newCoin === this.selectedCoin) {
self.select(eventData.prevCoin);
}
});
$scope.$watch('amount', function(newAmount, oldAmount) {
let eventData = {
newAmount: newAmount,
oldAmount: oldAmount,
coin: self.selectedCoin,
type: self.type
};
self.changeCounterPrice(eventData)
});
$scope.$on(counterChangedEvent, function (event, eventData) {
_.debounce(function () {
let pair = self.type === 'deposit' ? self.selectedCoin.toUpperCase() + eventData.coin.toUpperCase() :
eventData.coin.toUpperCase() + self.selectedCoin.toUpperCase();
Price.all(pair).all('latest').getList().then(function (priceList) {
let basePrice = priceList[0].ask;
$scope.amount = eventData.newAmount * basePrice;
});
}, AMOUNT_CHANGE_DEBOUNCE);
});
}
}
export default coinInputComponenet;
CoinDirective
'use strict';
import coinTpl from './coin.html';
function coinComponent($log) {
'ngInject';
var directive = {
restrict: 'E',
templateUrl: coinTpl,
controller: coinController,
controllerAs: 'vm',
bindToController: true,
scope: {
selected: '@',
expanded: '@',
name: '@',
iconSrc: '@',
iconClass: '@',
select: '='
}
};
return directive;
function coinController ($scope) {
'ngInject';
// TODO: migrate to conf
let self = this;
this.selectCurrent = function () {
self.select(self.name);
self.selected = true;
};
$scope.$on('reset', function() {
self.selected = false;
});
}
}
export default coinComponent;
The error I get is:
TypeError: self.changeCounterPrice is not a function
at coininput.directive.js:68
at Scope.$digest (angular.js:18210)
at Scope.$apply (angular.js:18480)
at bootstrapApply (angular.js:1952)
at Object.invoke (angular.js:5040)
at doBootstrap (angular.js:1950)
at bootstrap (angular.js:1970)
at Object.angular.bootstrap (ocLazyLoad.js:760)
at HTMLDocument.<anonymous> (index.bootstrap.js:18)
at mightThrow (jquery.js:3583)
(The same for postSelect
)
Stack trace:
(anonymous) @ angular.js:14642
(anonymous) @ angular.js:11102
$digest @ angular.js:18228
$apply @ angular.js:18480
bootstrapApply @ angular.js:1952
invoke @ angular.js:5040
doBootstrap @ angular.js:1950
bootstrap @ angular.js:1970
angular.bootstrap @ ocLazyLoad.js:760
(anonymous) @ index.bootstrap.js:18
mightThrow @ jquery.js:3583
process @ jquery.js:3651
setTimeout (async)
(anonymous) @ jquery.js:3689
fire @ jquery.js:3317
fireWith @ jquery.js:3447
fire @ jquery.js:3455
fire @ jquery.js:3317
fireWith @ jquery.js:3447
ready @ jquery.js:3920
completed @ jquery.js:3930
What is super weird, is that for select
works just fine! (two way bound function, by reference from the isolated scope of coinInputDirective
to coinDirective
)