Angularjs ng-model doesn't work inside ng-if

Angularjs

Angularjs Problem Overview


Here is the fiddle showing the problem. http://jsfiddle.net/Erk4V/1/

It appears if I have an ng-model inside of an ng-if, the model does not work as expected.

I am wondering if this is a bug or if I am misunderstanding the proper usage.

<div ng-app >
    <div ng-controller="main">
        
        Test A: {{testa}}<br />
        Test B: {{testb}}<br />
        Test C: {{testc}}<br />
        
        <div>
            testa (without ng-if): <input type="checkbox" ng-model="testa" />
        </div>
        <div ng-if="!testa">
            testb (with ng-if): <input type="checkbox" ng-model="testb" />
        </div>
        <div ng-if="!someothervar">
            testc (with ng-if): <input type="checkbox" ng-model="testc" />
        </div>
        
    </div>
</div>

Angularjs Solutions


Solution 1 - Angularjs

The ng-if directive, like other directives creates a child scope. See the script below (or this jsfiddle)

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0rc1/angular.min.js"></script>

<script>
    function main($scope) {
        $scope.testa = false;
        $scope.testb = false;
        $scope.testc = false;
        $scope.obj = {test: false};
    }
</script>

<div ng-app >
    <div ng-controller="main">
        
        Test A: {{testa}}<br />
        Test B: {{testb}}<br />
        Test C: {{testc}}<br />
        {{obj.test}}
        
        <div>
            testa (without ng-if): <input type="checkbox" ng-model="testa" />
        </div>
        <div ng-if="!testa">
            testb (with ng-if): <input type="checkbox" ng-model="testb" /> {{testb}}
        </div>
        <div ng-if="!someothervar">
            testc (with ng-if): <input type="checkbox" ng-model="testc" />
        </div>
        <div ng-if="!someothervar">
            object (with ng-if): <input type="checkbox" ng-model="obj.test" />
        </div>
        
    </div>
</div>

So, your checkbox changes the testb inside of the child scope, but not the outer parent scope.

Note, that if you want to modify the data in the parent scope, you'll need to modify the internal properties of an object like in the last div that I added.

Solution 2 - Angularjs

You can use $parent to refer to the model defined in the parent scope like this

<input type="checkbox" ng-model="$parent.testb" />

Solution 3 - Angularjs

You can use ngHide (or ngShow) directive. It doesn't create child scope as ngIf does.

<div ng-hide="testa">

Solution 4 - Angularjs

We had this in many other cases, what we decided internally is to always have a wrapper for the controller/directive so that we don't need to think about it. Here is you example with our wrapper.

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0rc1/angular.min.js"></script>

<script>
    function main($scope) {
    	$scope.thisScope = $scope;
        $scope.testa = false;
        $scope.testb = false;
        $scope.testc = false;
        $scope.testd = false;
    }
</script>

<div ng-app >
    <div ng-controller="main">

        Test A: {{testa}}<br />
        Test B: {{testb}}<br />
        Test C: {{testc}}<br />
        Test D: {{testd}}<br />

        <div>
            testa (without ng-if): <input type="checkbox" ng-model="thisScope.testa" />
        </div>
        <div ng-if="!testa">
            testb (with ng-if): <input type="checkbox" ng-model="thisScope.testb" />
        </div>
        <div ng-show="!testa">
            testc (with ng-show): <input type="checkbox" ng-model="thisScope.testc" />
        </div>
        <div ng-hide="testa">
            testd (with ng-hide): <input type="checkbox" ng-model="thisScope.testd" />
        </div>

    </div>
</div>

Hopes this helps, Yishay

Solution 5 - Angularjs

Yes, ng-hide (or ng-show) directive won't create child scope.

Here is my practice:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0rc1/angular.min.js"></script>

<script>
    function main($scope) {
        $scope.testa = false;
        $scope.testb = false;
        $scope.testc = false;
        $scope.testd = false;
    }
</script>

<div ng-app >
    <div ng-controller="main">

        Test A: {{testa}}<br />
        Test B: {{testb}}<br />
        Test C: {{testc}}<br />
        Test D: {{testd}}<br />

        <div>
            testa (without ng-if): <input type="checkbox" ng-model="testa" />
        </div>
        <div ng-if="!testa">
            testb (with ng-if): <input type="checkbox" ng-model="$parent.testb" />
        </div>
        <div ng-show="!testa">
            testc (with ng-show): <input type="checkbox" ng-model="testc" />
        </div>
        <div ng-hide="testa">
            testd (with ng-hide): <input type="checkbox" ng-model="testd" />
        </div>

    </div>
</div>

http://jsfiddle.net/bn64Lrzu/

Solution 6 - Angularjs

You can do it like this and you mod function will work perfect let me know if you want a code pen

  <div ng-repeat="icon in icons">			        
		        <div class="row" ng-if="$index % 3 == 0 ">
		            <i class="col col-33 {{icons[$index + n].icon}} custom-icon"></i>
		            <i class="col col-33 {{icons[$index + n + 1].icon}} custom-icon"></i>
		            <i class="col col-33 {{icons[$index + n + 2].icon}} custom-icon"></i>
		        </div>
		 </div>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJustin CarlsonView Question on Stackoverflow
Solution 1 - AngularjsJon7View Answer on Stackoverflow
Solution 2 - Angularjszs2020View Answer on Stackoverflow
Solution 3 - AngularjsVasiliy KevroletinView Answer on Stackoverflow
Solution 4 - AngularjsYishay HaspelView Answer on Stackoverflow
Solution 5 - AngularjsXiayan YView Answer on Stackoverflow
Solution 6 - AngularjsCesar VegaView Answer on Stackoverflow