4

Angular - The changing range is not reflected

 3 years ago
source link: https://www.codesd.com/item/angular-the-changing-range-is-not-reflected.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Angular - The changing range is not reflected

advertisements

This is weird as it should be pretty straightforward. I will post my code first and then ask the question:

html -

<div ng-controller="myController" ng-switch on="addressCards">

    <div>
        {{addCustom}} // does not get changed
        <div ng-if="addCustom === false">

            {{addCustom}} // does get changed
            <button type="button" class="btn btn-primary btn-icon-text" ng-click="addCustom = true">
                <span class="icon icon-plus"></span>
                click here
            </button>
        </div>
    </div>
</div>

controller -

(function(){
'use strict';

angular.module('myApp')
    .controller('myController',['$scope',myController]);

function myController($scope){ 

    $scope.addCustom = false;

}

})();

So I simply introduced a scope variable - addCustom - in my controller and set it to false as default. This variable controls if a div is shown or not. I am also outputting the value of the scope on the html at 2 different locations. Please see above.

But when I change its value in an ng-click within this divs, its value is changing at the second location(within the div) but not the first one(outside the div). Because of this the div does not change state as well.

I am not able to figure what might be possibly wrong here. Can someone please help?


The thing happening is when you have ng-repeat,ng-switch and ng-if directive, angular creates child scope for those element wherever they are placed. Those newly created scope are prototypically inherited from there parent scope.

On contrast Prototypal Inheritance means?

If you have scope hierarchy, then parent scope property are accessible inside child scope, only if those property are object (originally object referenced is passed to child scope without creating its new reference). But primitive datatypes are not accessible inside child scope and if you looked at your code addCustom scope variable is of primitive dataType.


Lets discuss more about it.

Here you have myController controller which has addCustom scope variable of primitive type & as I said above ng-switch & ng-if directive are compiled they do create new child scope on that element. So in your current markup you have ng-switch on ng-controller="myController" div itself. For inner html it had created a child scope. If you wanted to access parent scope inside child(primitive type) you could use $parent notation before scope variable name. Now you can access the addCustom value by $parent.addCustom. Here its not over when angular compiler comes to ng-if div, it does create new child scope again. Now inner container of ng-if will again have child scope which is prototypically inherited from parent. Unfortunately in your case you had primitive dataType variable so you need to use $parent notation again. So inside ng-if div you could access addCustom by doing $parent.$parent.addCustom. This $parent thing will solve your problem, but having it on HTML will make unreadable and tightly couple to its parent scope(suppose on UI you would have 5 child scope then it will look so horrible like $parent.$parent.$parent.$parent). So rather you should go for below approach.


Follow Dot rule while defining ng-model

So I'd say that you need to create some object like $scope.model = {} and add addCustom property to it. So that it will follow the prototypal inheritance principle and child scope will use same object which have been created by parent.

angular.module('myApp')
.controller('myController',['$scope',myController]);
 function myController($scope){
    $scope.model = { addCustom : false };
}

And on HTML you will use model.addCustom instead of addCustom

Markup

<div ng-controller="myController" ng-switch on="addressCards">
    <div>
        {{model.addCustom}} // does not get changed
        <div ng-if="model.addCustom === false">

            {{model.addCustom}} // does get changed
            <button type="button" class="btn btn-primary btn-icon-text" ng-click="model.addCustom = true">
                <span class="icon icon-plus"></span>
                click here
            </button>
        </div>
    </div>
</div>

Other best way to deal with such kind of issue is, use controllerAs pattern while using controller on HTML.

Markup

<div ng-controller="myController as myCtrl" ng-switch on="addressCards">
    <div>
        {{myCtrl.addCustom}} // does not get changed
        <div ng-if="myCtrl.addCustom === false">

            {{myCtrl.addCustom}} // does get changed
            <button type="button" class="btn btn-primary btn-icon-text" ng-click="myCtrl.addCustom = true">
                <span class="icon icon-plus"></span>
                click here
            </button>
        </div>
    </div>
</div>




About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK