I am trying to have radio buttons controlling boolean properties of external objects through getters and setters.
In the following example, there are multiple Person, but only one can be happy. One of them is already happy. I want to control which one is happy through radio buttons.
Therefore, I created a template with a radio input, but I can't bind it to person.happy, as I don't have access to this property (suppose Person is a third-party library).
In order to bind something to the input, I created a dumb controller, to provide a default value (the Person value), and propagate changes to the real variable (in short, call the setter). I can't seem to get things right.
var app = angular.module('app', []);
// Person constructor ; happy is a private member
function Person(name, isHappy) {
var happy = isHappy;
this.name = name;
this.getHappy = function() { return happy; }
this.setHappy = function(value) { happy = value; }
}
// Inject a person list in the scope
app.controller('PeopleCtrl', function($scope) {
$scope.people = [
new Person('Alice', true),
new Person('Bob', false),
new Person('Carol', false)
];
});
// Template to display one person + happiness controller
var humanTemplate = [
'<div><label>',
'<input type="radio" name="group" ng-model="me.happy" ng-change="me.toggle()" value="{{ !me.happy }}">',
'<span>{{ person.name }} is {{ me.happy ? "happy" : "sad" }}</span>',
'</label></div>'
].join('');
// Directive to display one person
app.directive('human', function() {
return {
restrict: 'E',
template: humanTemplate,
scope: {
person: '='
},
controllerAs: 'me',
controller: function($scope) {
var me = this;
me.happy = $scope.person.getHappy();
me.toggle = function() {
console.log(me.happy);
$scope.person.setHappy(me.happy);
};
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<div ng-app="app" ng-controller="PeopleCtrl">
<human ng-repeat="p in people" person="p"></human>
</div>
I would have thought ngChange would be tied to the checked state on radio and checkboxes (would have been somehow logical), but there are symptoms telling me otherwise:
ngChangeis not fired for the previously checked radiongChangeis not fired more than once (I got it to fire twice when messing with the inputvalueattribute)
I may be mistaken since I am a beginner, but it looks like ngChange is not what I want.
What do you think would be a good solution for this problem? Do I need to write a parent controller to manage manually the deactivation of some items when the other get activated?