I'm having trouble with a bi-directional binding in an ng-repeat. I would expect for the below $watch to be triggered when you select a color from the list.
$scope.$watch('favoriteColors', function (newValue) {
console.log('example-favoriteColors', newValue);
});
I would expect for Orange to appear in $scope.favoriteColors when checked.
Example: http://plnkr.co/edit/k5SEQw4XFnxriD2I8ZG7?p=preview
directive('checkBox', function () {
return {
replace: true,
restrict: 'E',
//require: '^ngModel',
scope: {
'externalValue': '=ngModel',
'value': '&'
},
template: function (el, attrs) {
var html =
'<div class="ngCheckBox">'+
'<span ng-class="{checked: isChecked}">' +
'<input type="checkbox" ng-model="isChecked"/>'+
'</span>'+
'</div>';
return html;
},
controller: ['$scope', '$timeout', function ($scope, $timeout) {
var initialized = false;
console.log($scope.value());
if (angular.isArray($scope.externalValue)) {
$scope.isChecked = $scope.externalValue.indexOf($scope.value()) > 0;
} else {
$scope.isChecked = !!$scope.externalValue;
}
$scope.$watch('isChecked', function (newValue) {
if (angular.isDefined(newValue)) {
//add or remove items if this is an array
if (angular.isArray($scope.externalValue)) {
var index = $scope.externalValue.indexOf($scope.value());
if(index > -1) {
$scope.externalValue.splice(index, 1);
} else if (initialized) {
$scope.externalValue.push($scope.value());
}
} else {
//simple boolean value
$scope.externalValue = newValue;
}
if (initialized)
console.log($scope.externalValue);
}
});
$timeout(function () {
initialized = true;
});
}],
link: function (scope, el, attrs) {
}
};
});
Please check out this plunk: http://plnkr.co/edit/pbHz4ohBPi7iYq6uJI8X?p=preview
There were lots of changes. Some of them are:
initialized (and consequently the $timeout) is not needed.indexOf function; there is a chance the objects are not the same in == sense, but equals in the x.name === y.name sense; (I have some doubts about this though)add or remove items if this is an array part was wrong; you need to update the array based on the value of isChecked, not based on whether the item already exists in the array (indexOf).favoriteColors as an array, not as a single object, to be consistent, i.e. $scope.favoriteColors = [$scope.colors[1]];favoriteColors change.$watch("favoriteColors", function() {...}, true) to watch for changes inside the array (not the true last argument).If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With