IIFE in AngularJS
Asked Answered
C

2

9

I've specified a function in my controller like this:

$scope.myFunction = function(){ console.log('test'); }

I want this function to be triggered when a selectbox has been changed. Therefore I apply ng-change on the select element like this:

 <select ng-options="..." ng-model="..." ng-change="myFunction();"></select>

But I also want the myFunction function to be triggered when my page is loaded. So I thought to turn my function into a IIFE:

($scope.myFunction = function(){ console.log('test'); }());

However, now the function is only triggered on pageload and not by ng-change. I noticed that when I change the parenthesis, the function also gets triggered by ng-change:

($scope.myFunction = function(){ console.log('test'); })();

Can someone explain why this even matters?

Thanks alot!

Colp answered 3/9, 2014 at 12:57 Comment(2)
The first invocation is not an IIFE, the second is.Idiot
@Idiot according to this article benalman.com/news/2010/11/…, both of the versions are IIFEs, with slight differences Such parens typically indicate that the function expression will be immediately invoked, and the variable will contain the result of the function, not the function itself. This can save someone reading your code the trouble of having to scroll down to the bottom of what might be a very long function expression to see if it has been invoked or not.Cephalonia
D
10

There is a huge difference between this

($scope.myFunction = function(){ console.log('test'); }());

And this

($scope.myFunction = function(){ console.log('test'); })();

Because the first line assigns the result of the function call, and then only stores it, but it's not a function that it stores.

The second works as expected because you call the function after having assigned it to $scope.myFunction

UPDATE

As helpermethod pointed out in comments, the first line is not an IIFE, because you're not calling the function itself, but only the result of it.

Dehydrogenase answered 3/9, 2014 at 13:2 Comment(1)
Ok, I get it now. The reason why I did the former was that JSLint was complaining about 'Bad invocation' of the function.Colp
E
7

Without seeing all of your code it is hard to tell. You are not using an IIFE, you are executing your own function and setting it to the $scope variable. Also, an IIFE will not make it run on page load. Instead of trying to correct all of that, try using code more like the example below.

Try creating a controller in an IIFE and updating your HTML like this:

<div ng-controller="MyCtrl as vm">
     <select ng-options="vm.someOptions" 
        ng-model="vm.someModel" 
        ng-change="vm.myFunction()"></select>
</div>

and your controller

(function(){
    angular.module('myapp').controller('MyCtrl', MyCtrl);

    function MyCtrl() {
        var vm = this;

        vm.someModel; 
        vm.someOptions = []; // set these
        vm.myFunction = myFunction;

        activate();

        function activate() {
            myFunction();
        }

        function myFunction() {
            // TODO: will be called onchange and
            // when controller starts
        }

    }

})();
Encumbrancer answered 3/9, 2014 at 13:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.