Question

I am having a very hard time trying to figure out a solution for this. I have a checkbox group where the first checkbox is the parent and the following in that set will be child. I want the parent checkbox to be selected automatically if one of the child's checkbox is selected. Similarly parent needs to be get unchecked if no child is selected.

Here is my jsfiddle example: http://jsfiddle.net/Alien_time/PqTR7/3/

The main difficulty I am facing is because the checkboxes are created dynamically and it has dynamic ng-models for each. I have tried the following so far:

1) ng-checked: This doesnt work for me since ng-checked doesnt bind the value with ng-model. I need the ng-model of the parent to be updated as well since this is going to reflect in the main form.

2) JS solution: I thought js method will be the solution, but dont know how to add the js to controller as the ng-model is dynamically generated.

3) On other posts, there are some method that uses select all when parent is checked. But I couldnt find a solution for my approach since its the other way around where I only want the parent selected if one of the child is selected.

For my form, I need to have a different ng-model for each checkbox thats why I am using the name to create a dynamic ng-model name. But I just couldnt figure out how to select the parent checkbox if a child is selected in this dynamic list.

I have been stuck on this for 2 days and searched a lot on the net. Can you help me please?

Was it helpful?

Solution

HERE is the working solution based on your fiddle.

JS

$scope.select = function(index){
    if(index === 0){
        $scope.slaves.forEach(function(slave, ind){
            $scope.slaves[ind].isChecked = $scope.slaves[0].isChecked;
        });
    }
    else {
        var anyChild = false;
        for(var i = 1; i < $scope.slaves.length; i++){
            anyChild = anyChild || $scope.slaves[i].isChecked; 
        }
        $scope.slaves[0].isChecked = anyChild;
    }
}

HTML

<div ng-repeat="slave in slaves">
    <input type="checkbox" ng-model="slave.isChecked" ng-click="select($index)" />
    {{slave.name}} -  {{ slave.description }}
</div>

To tell the truth I do not find the solution elegant -- you would be better off by encapsulating the logic of it in a custom directive. Moreover it would be probably better to express parent-child relation by:

var parent = {
   ... // parent data
   childeren : [child_1, ... , child_N] // array of children
} 

OTHER TIPS

A solution to this problem is to add a watch.

Add the following in your controller

$scope.$watch('checkboxData', function (newValue, oldValue) {
    var anyChecked = false;
    // see if any are checked
    $scope.slaves.reduce(function (pVal, cVal, idx, arr) {
        if (newValue[cVal.name]) anyChecked = anyChecked || newValue[cVal.name];
    });
    // replace the parent 'checked' in the model
    $scope.checkboxData['Parent'] = anyChecked;
}, true);

And add the following to your input elements.

ng-checked='checkboxData[slave.name]'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top