Search code examples
javascriptangularjsangularjs-scopeangular-directive

Angular directive scope not accessible in parent controller


I am working on a angular applicaiton I stucked in a issue regarding calling direcive method into parent controller . Problem is i am using login directive on profile controller . I want to call login direcive's method from profile controller's scope.

Firstproblem is i an not able to call login directives's method by using $scope.login.openLogin(false) in controller because $scope.login is undefined here. However in same controller $scope.login.openLogin(false) is accessible in call back event like ajax call's success or error method. But i don't know some time is also given undefined and some time working fine .This is my main problem not able to find out why some time $scope.login accessible and some time not .

First problem is i am not able to get $scope.vm or $scope.login in profile controller.I cant call method like $sope.vm.getData() instead i have to call it like this.getData() .Why this.getData() is accessible but $scope.vm.getData() not accessible it gives null

Following is the code of login directive

LoginDirective.cs

//Login diretive 
angular.module('EmailApp')
    .directive('login', function LoginDrctv() {
        'use strict';
        return {
            restrict: 'EA',
            replace: true,
            scope: false,
            templateUrl: "js/directives/template/login.tmpl.html",
            controllerAs: 'login',
           //bindToController: true,
            controller: function (LoginFactory, $scope, $rootScope, $location) {

                //THis method is to be call from parent controller (Profile Controller)
                this.openLogin = function (IsmakeCall) {
                    debugger;
                    this.loginOperation = "Login";
                    this.makeCall = IsmakeCall;   //true or false
                  //  $rootScope.islogin = true;
                    $scope.vm.mainPage = 'login';
                }
            },
            link: function (scope, element, attrs, ctrl) {
                /* 
                  by convention we do not $ prefix arguments to the link function
                  this is to be explicit that they have a fixed order
                */
            }
        }
    });

Profile Controller (Profile.Js)

angular.module('EmailApp')
    .controller('ProfileCtrl', ['$rootScope', '$routeParams', 'DetailFactory', '$scope', '$location',
        function ProfileCtrl($rootScope, $routeParams, DetailFactory, $scope, $location) {

            'use strict';
            this.loading = true;
            this.mainPage = 'detail';
            this.back = function () {
                $location.path('home');
            }
           // $scope.login.openLogin(false)  this method is not accessible 
           //here but in call back function is works like below
            this.getData = function () {
                debugger;
                this.loading = true;
                DetailFactory.getDetailProfile().then(function (resp) {
                    $scope.vm.loading = false;
                    $scope.vm.userDetails = resp.data;
                    $scope.vm.userId = resp.data.appUser.UserID
                }, function (err) {
                    $scope.vm.loading = false;
                    if (err.status == 401) {
                        //Call method of login directive .It get called some 
                        //times but sometime $scope.login gives undefined
                        $scope.login.openLogin(false);
                    }
                });
            }
            this.getData();
        }]);

profile.html

angular.module('EmailApp', [
    'ngRoute',
    'ngSanitize',
    'angularFileUpload'
]).config(function ($routeProvider) {

    'use strict';
    $routeProvider
        .when('/profile', {
            templateUrl: 'view/profile.html?v=' + Math.random(),
            controller: 'ProfileCtrl',
            controllerAs: 'vm'
        })
        .when('/home', {
            templateUrl: 'view/PrivacyPolicy.html?v=' + Math.random(),
            controller: 'PrivacyCtrl',
            controllerAs: 'vm'
        })
        .otherwise({
            redirectTo: '/home'
        });
    }).run(function ($rootScope, $location) {
});

Solution

  • In general a parent controller does not make a function call into a child controller or directive. Instead pass a value into the directive DOM and add a $watch on the directive to know when that value has changed.

    Here is some code that does a $watch

    <!DOCTYPE html>
    <html ng-app="myApp">
      <head>
        <meta charset="utf-8">
        <title>Angular Callback</title>
        <style>
        .login {
          border: 1px solid black;
        }
    
        .login:not(.login--opened) .login-inner {
          display: none;
        }
        </style>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
        <script>
        var myApp = angular.module("myApp", []);
    
        myApp.controller('appController', function($scope) {
          $scope.loginIsOpen = false;
    
          $scope.openLogin = function() {
            $scope.loginIsOpen = true;
          }
    
        });
    
    
        myApp.controller('loginController', loginController);
        loginController.$inject = ['$scope'];
        function loginController($scope) {
          $scope.closeMe = function() {
            $scope.isOpen = false;
          }
    
          $scope.$watch('isOpen', function(newVal) {
            if (newVal === true) {
              console.log('The Login was opened');
            }
          });
        }
    
        myApp.directive('login', loginDirective );
        function loginDirective() {
          return {
            'restrict': 'E',
            'template': '<div class="login" ng-class="{\'login--opened\':isOpen}">Login Directive<div class="login-inner"><p>I am open</p><button ng-click="closeMe()">Close</button></div></div>',
            'controller': 'loginController',
            'scope': {
              isOpen: '='
            }
          };
        }
        </script>
      </head>
      <body ng-controller="appController">
        <button ng-click="openLogin()">Open Login</button>
        <hr/>
        <login is-open="loginIsOpen"></login>
      </body>
    </html>