Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular ng-model changes to undefined when checkbox on ng-repeat has the required attribute

I have an array of applications. A subset of that array is pushed into another array.

$scope.applicant.selectedApps = [];
$scope.applicant.applications = applications;
angular.forEach(applications, function (application) {
    if(application.isSelected){
        $scope.applicant.selectedApps .push(application);
    }
}

I know have 2 ng-repeats that loop over those arrays:

 <div class="row">
        <div class="form-group col-sm-10 col-sm-offset-1">
            <div class="radio">
                <label>
                    <input type="radio" name="intent" ng-model="applicant.intent" value="Y" required />YES
                </label>
            </div>
            <div class="row" ng-show="applicant.intent == 'Y'">
                <div class="col-xs-11 col-xs-offset-1">
                    <div class="row" ng-repeat="app in applicant.selectedApps">
                        <div class="col-sm-11 col-sm-offset-1">
                            <div class="checkbox">
                                <label>
                                    <input id="Prog{{app.appid}}" name="Progs" type="checkbox" ng-model="app.isSelected" ng-change="appChange(app)"  ng-required="applicant.intent == 'Y'" />
                                    {{app.Objective}} - {{app.Name}} - {{app.Description}}
                                </label>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

<div class="row">
        <div class="form-group col-sm-10 col-sm-offset-1">
            <div class="radio">
                <label>
                    <input type="radio" name="intent" ng-model="applicant.intent" value="N" required />NO
                </label>
            </div>
            <div class="row" ng-show="applicant.intent == 'N'">
                <div class="col-xs-11 col-xs-offset-1">
                    <div class="row" ng-repeat="dApp in applicant.applications">
                        <div class="col-sm-11 col-sm-offset-1">
                            <div class="checkbox">
                                <label>
                                    <input id="dProg{{dApp.appid}}" name="dProgs" type="checkbox" ng-model="dApp.isSelected" ng-change="dProgChange(dApp)" ng-required="applicant.intent == 'N' && appCount <= 0" />
                                    {{dApp.Objective}} - {{dApp.Name}} - {{dApp.Description}}
                                </label>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

the two change functions are as followed:

$scope.dProgChange = function (app) {
    if (app.isSelected) {
        $scope.appCount++;
    } else {
        $scope.appCount--;
    }
};

$scope.ProgChange = function (app) {
    if (app.isSelected) {
        $scope.selectedAppCount++;
    } else {
        $scope.selectedAppCount--;
    }
};

What i observe is that every app that was initializes with "isSelected" = false will be set to undefined as soon as the radio button is switched to "NO". When switched back to "YES" is selected switches back to false.

This causes the dProgChange to trigger every time the Radio button value changes.

I can't figure out why the "isSelected" switches to undefined.

UPDATE While trying to create a simplified example, i noticed that the problem occurs as soon as the checkbox is required. In the plunker listed bellow, the model value for the checkbox is set to undefined as soon as the checkbox is unchecked. That seems to me the same issue i am having.

http://plnkr.co/edit/SBsdew8tzWdNgNOf6W1c?p=info

like image 464
Seb81 Avatar asked Mar 19 '15 22:03

Seb81


2 Answers

This is the way AngularJS (ng-model and NgModelController) is supposed to work.

NgModelController has two properties: $viewValue (value entered by user) and $modelValue (value bound to your model). When the value entered by the user fails validation, NgModelController sets the model to undefined.

In AngularJS 1.3, they added the ng-model-options directive. It lets you configure how/when the model gets updated. You can use the allowInvalid option to prevent your model from being set to undefined:

<input type="checkbox"
    ng-model="myModel.value"
    ng-model-options="{allowInvalid: true}">
like image 80
Sunil D. Avatar answered Nov 08 '22 19:11

Sunil D.


So, I am going to add to this answer for future reference. This applies to <input> also. If you have something such as

<input ng-model="speaker.vrange" ng-blur= "updateSpkV()" type="number" data-placement="right" min ="0" max="10"/>

then you will have an invalid input if you set the value to something outside of the range and the model variable will be set to undefined. This became an issue with me when I directly entered an out of bound value rather than using up/down arrows for adjusting a value.

like image 34
cirrusio Avatar answered Nov 08 '22 20:11

cirrusio