1

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.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
Jeffrey Roosendaal
  • 6,872
  • 8
  • 37
  • 55
  • The question is not "that it does some unexpected things", I was stating that "I'm wondering what's happening behind the scenes when using ng-init", and my question was "Which element does myVar bind to?". – Jeffrey Roosendaal Jul 21 '17 at 14:17
  • 1
    The [ng-init directive](https://docs.angularjs.org/api/ng/directive/ngInit) 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 [AngularJS Developer Reference - scopes](https://docs.angularjs.org/guide/scope). See also [AngularJS Wiki - Nuances of Scope Prototypical Inheritance](https://github.com/angular/angular.js/wiki/Understanding-Scopes). – georgeawg Jul 21 '17 at 18:32
  • Thanks, that was exactly what I was looking for! If you can update your answer with this, I will gladly mark it as accepted. – Jeffrey Roosendaal Jul 24 '17 at 08:56
  • Updated answer. – georgeawg Jul 24 '17 at 11:11

1 Answers1

1

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.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • Thanks for the reference, however, this does not answer my question about the bindings. I've also added an example of a code block I sometime use. – Jeffrey Roosendaal Jul 21 '17 at 09:20