UI_Dev
UI_Dev

Reputation: 3427

how to define normal javascript function inside the controller in angularjs

I have a code snippet below.

sample.js

(function() {
    /*global angular */
    'use strict';

    angular.module('myapp', ['spinner'])
       .controller('myCtrl', ['$scope', '$window', function ($scope, $window ) {

    $scope.methodname = function() {
            if(something){
                /* Doing some operations */
            }
    };
    /* Here I need to define the callme javascript function */

   function callme(response){
       /* If I call like this, I'm getting error in console. */
    }

    }]);  /* Controller ends here */

    /* Creating a new anonymous function to perform some operations */
    (function () {
    'use strict';


     /* Edited */
   code.util.myHTTP(url, function (response) {

             // Adding response to session storage
            callme(response);

             }, function () {
               // Removing from session storage
        });

        })();
     }());

Here, I can't able to call callme javascript function inside angular controller . I'm getting error in console like

Uncaught ReferenceError: callme is not defined

Is there any way to achieve this?

I need to use some controller parameters like $window inside callme function, that's why I'm defining callme function inside controller.

I have run function in my js file already like below

.run(function($rootScope, $log, $window) {
});

My requirement is like call anonymous function, on load there will be some api response, I need to call one method to process the response. because of these controller parameters, I wanted to define my method inside the controller. Is there any alternate way to achieve this?

Upvotes: 0

Views: 1190

Answers (1)

Dan
Dan

Reputation: 10548

Your indentation is all over the place and is what makes this code hard to understand. Here's your correctly formatted code..

(function () {
  /*global angular */
  'use strict';

  angular.module('myapp', ['spinner'])
    .controller('myCtrl', ['$scope', '$window', function ($scope, $window) {
      $scope.methodname = function () {
        if (something) {
          /* Doing some operations */
        }
      };
      /* Here I need to define the callme javascript function */

      function callme (response) {
        /* If I call like this, I'm getting error in console. */

      }
    }]); /* Controller ends here */

  /* Creating a new anonymous function to perform some operations */
  (function () {
    'use strict';

    /* Edited */
    code.util.myHTTP(url, function (response) {

      // Adding response to session storage
      callme(response);
    }, function () {
      // Removing from session storage
    });
  })();
}());

The reason this doesn't work is because function declarations are hoisted to the top of their scope, but do not exist outside of that scope. If we remove some cruft, this is what your code simplifies to:

(function() {
  function MyController($scope) {
    $scope.methodname = function() {}

    function callme(response) {
    }
  }

  (function() {
    callme()
  }())
}())

callme is hoisted, but only to the top of MyController. That symbol doesn't exist outside of that scope, and that's why you can't do callme() in your nested scope.

What you are doing seems like an anti-pattern; even if you could achieve this, core.util.myHTTP would not execute within the Angular digest cycle, so you'd have to call $scope.$apply inside of your controller, which is generally considered a bad thing. Why not just use $http instead?

Nevertheless, if you really want to do this (and you don't), you could define your function like so:

(function() {
  function callme(response) { }

  function MyController($scope) {}

  (function() {
    ...
    callme()
  }())
}())

Alternatively you could use directives (or components, depending on your angular version) to handle this instead.. which is how it should be done.

function SpinnerCtrl($http) {
  this.$http = $http
}
SpinnerCtrl.$inject = ['$http']
SpinnerCtrl.onInit = function onInit() {
  var that = this
  return this.$http.get(url)
    .then(function (response) {
      // Store it in session storage, do whatever.
      // Presumably there's some data you want to make accessible to other parts of the app, so I assign it to the controller here
      that.response = response
    })
}

angular.module('myapp', ['spinner'])
  .component('spinner', {
    controller: SpinnerCtrl,
    template: '<h1>{{ $ctrl.response }}</h1>'
  })

// or

function SpinnerCtrl($scope, $http) {
  return $http.get(url).then(function (response) {
    $scope.response = response
  })
}

angular.module('myapp', ['spinner'])
  .directive('spinner', function () {
    return {
      controller: SpinnerCtrl,
      template: '<h1>{{ response }}</h1>'
    }
  })

Note that really you should move the $http call to a service and handle the session storage in there too; the session storage thing is implementation detail and the component/directive using it should not have to care. I haven't done that just for brevity.

Upvotes: 1

Related Questions