javascriptangularjsdata-bindingangularjs-ng-init

Which element does myVar bind to? Problems with `ng-init`


I'm wondering what's happening behind the scenes when using ng-init.

Sometimes ng-init does some unexpected things, and I have a hard time debugging.


Let's say I have the following structure:

<!-- App -->
<div ui-view>

    <!-- Component -->
    <custom-component>

        <!-- Transcluded component -->
        <transcluded-component>

            <!-- Controller -->
            <div ng-controller="MyCtrl">

                <!-- Element -->
                <div ng-init="myVar = 'hello'">

                    {{myVar}}

                </div>
            </div>
        </transcluded-component>
    </custom-component>
</div>

Which element does myVar bind to?


Edit 2017-07-21: Added an example

In the following template block (especially within an ng-repeat), I may use an ng-init:

<span ng-init="path = getPath()">
    <a ng-if="path" ng-href="path">
        Click here
    </a>
    <span ng-if="!path">
        Some text
    </span>
</span>

In this case, I skipped a function call twice, and kept my template clean.


Solution

  • Sometimes ng-init does some unexpected things, and I have a hard time debugging.

    The ng-init directive evaluates an Angular Expression in the context of the scope of its element. Numerous directives (ng-repeat, ng-controller, ng-if, ng-view, etc.) create their own scope.

    For more information, see


    Avoid using ng-init

    Avoid using ng-init. It tangles the Model and View, making code difficult to understand, debug and maintain. Instead initialize the Model in the controller.

    From the Docs:

    ngInit

    This directive can be abused to add unnecessary amounts of logic into your templates. There are only a few appropriate uses of ngInit, such as for aliasing special properties of ngRepeat, as seen in the demo below; and for injecting data via server side scripting. Besides these few cases, you should use controllers rather than ngInit to initialize values on a scope.

    — AngularJS ng-init Directive API Reference


    Update

    Q: I've also added an example of a code block I sometime use.

            <!-- Controller -->
            <div ng-controller="MyCtrl">
                <!-- Element -->
                <div ng-init="myVar = 'hello'">
                    {{myVar}}
                </div>
            </div>
    

    To do the equivalent initialization in the controller:

    app.controller("MyVar", function($scope) {
        this.$onInit = function() {
            $scope.myVar = 'hello';
        };
    });
    

    By separating concerns of Model and View, the code becomes easier to understand, debug and maintain.