简体   繁体   中英

AngularJS controller function not firing

I have 3 directives, "parenta", "parentb", and "childb". "parenta" and "parentb" are siblings, while "childb" is a direct child of "parentb".

I am trying to call a controller method from "parenta", however it is not working. For some strange reason, trying to call a method on "childb" controller FROM "parenta" is working instead. What is happening?

var mod = angular.module("app", []);

mod.directive("parenta", function () {
    return {
        template: "<section><div ng-click='vm.a()'>Rendered by a</div></section>",
        replace: false,
        controllerAs: "vm",
        controller: function () {
            this.a = function () {
                console.log("a called!");
            }
        }
    }
})

mod.directive("parentb", function () {
    return {
        template: "<childb></childb>",
        replace: false
    }
})

mod.directive("childb", function () {
    return {
        template: "<section><div ng-click='vm.b()'>Rendered by b</div></section>",
        replace: false,
        controllerAs: "vm",
        controller: function () {
            this.b = function () {
                console.log("b called!");
            }
        }
    }
})

Html:

<div ng-app="app">
    <parenta></parenta>
    <parentb></parentb>
</div>

Codepen: http://codepen.io/anon/pen/pJMpVe

The issue here is that your directives do not create a child or an isolate scope and use scope: false (which is the default).

That means that for a given scope, each directive with its aliased controller, create a scope property called vm - both on the same scope . And so, childb overwrites the vm property initially created by parenta .

You can check this quite easily - change one of controllerAs aliases to something else.

An easy fix - and the right thing to do - is to use either scope: true or scope: {} .

I used link function instead of controller.

Directive controllers are used in AngularJS for inter-directive communication, while link functions are fully contained and specific to the directive instance. By interdirective communication, we mean when one directive on an element wants to communicate with another directive on its parent or on the same element. This encompasses sharing state or variables, or even functions.

In the below code I commented the controller function and placed link function

 <!DOCTYPE html> <html> <head> <meta charset="ISO-8859-1"> </head> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script> <script type="text/javascript"> var mod = angular.module("app", []); mod.directive("parenta", function () { return { /*template: "<section><div ng-click='vm.a()'>Rendered by a</div></section>",*/ template: "<section><div ng-click='a()'>Rendered by a</div></section>", replace: false, link: function($scope,$element,$attrs) { $scope.a = function() { console.log("a called!"); } } /* controllerAs: "vm", controller: function () { this.a = function () { alert("a called!"); console.log("a called!"); } } */ } }) mod.directive("parentb", function () { return { template: "<childb></childb>", replace: false } }) mod.directive("childb", function () { return { template: "<section><div ng-click='vm.b()'>Rendered by b</div></section>", replace: false, controllerAs: "vm", controller: function () { this.b = function () { console.log("b called!"); } } } }) </script> <body> <div ng-app="app"> <parenta></parenta> <parentb></parentb> </div> </body> </html> 

or if we want to use controller directive then better to use Directive Isolate Scopes along with.

Unlike a controller, which is paired with a newly created scope when created, a directive is not given a scope of its own by default. Instead, it simply uses the scope that is available, based on its location in the DOM.

Isolate scope just means giving the directive a scope of its own that does not inherit from the existing scope.

so we use

scope: true in our parenta

 mod.directive("parenta", function () { return { template: "<section><div ng-click='vm.a()'>Rendered by a</div></section>", replace: false, scope: true , // Isolate scope controllerAs: "vm", controller: function () { this.a = function () { console.log("a called!"); } } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM