Param Singh
Param Singh

Reputation: 1366

AngularJS Factory access this methods from returning object

I have created an AngularJS factory in which I'm returning an object which has some functions as properties. My purpose is to call some function in another function from that returning using the this keyword but its giving an error. I tried to console.log the this keyword and I found out that, that this variable holds the scope of calling controller in which the factory is being injected. How can I tackle this kind of situation. this keyword should return the current returning object!

 app.module('admin').factory('login', [function() {
return {
    someFunc: function() {
        return 'abc'
    },
    anotherFunc : function(){

        var msg = this.someFunc();
        return 'Msg is '+ msg;

    },
    yetAnotherFunc : function(){

        var msg = this.someFunc();
        return 'Msg is '+ msg;

    }
}
}]).controller(['$scope', 'login', function($scope, login){
    login.someFunc(); // Works Fine
    login.anotherFunc(); // Error : this.someFunc is not a function
}])

Upvotes: 2

Views: 2298

Answers (3)

Steven
Steven

Reputation: 31

https://jsfiddle.net/6fwu7ghs/

HTML

<div ng-app="test" ng-controller="testController">
<input type="button" ng-click="testFunc2()" value="test2" />
<input type="button" ng-click="testFunc1()" value="test1" />
</div>

JS

var testModule = angular.module('test',[ ]);
testModule.controller('common' , function(  $scope ) {
$scope.testFunc1 = function(){
    alert("test1");
    };
});
testModule.controller('testController', function( $scope , $controller ){ 
//inherit
$controller('common', {
    $scope: $scope
});

$scope.testFunc2 = function (){
alert("test2");
};
});

how about this way. I'm just using controller with 'inherit'

Do you really need to use 'Factory' ? then this is not an answer.

Upvotes: 0

pablochan
pablochan

Reputation: 5715

Try this:

app.module('admin').factory('login', [function() {
    function someFunc() {
        return 'abc';
    }

    return {
        someFunc: someFunc,
        anotherFunc : function(){

            var msg = someFunc();
            return 'Msg is '+ msg;

        },
        yetAnotherFunc : function(){

            var msg = someFunc();
            return 'Msg is '+ msg;

        }
    };
}]).controller(['$scope', 'login', function($scope, login){
    login.someFunc();
    login.anotherFunc();
}]);

Now the someFunc will be visible in the scope of the returned object.

EDIT:

About the this issue, I think you're misunderstanding how this works in Javascript.

The this keyword will only work "properly" in certain circumstances:

  • you're invoking a function on an object that was created using the new keyword
  • you're invoking a bound function (see the docs)
  • you're invoking a function using call or apply and giving it a context (this)

Looking at Waxolunist's answer, I can see that the code you posted in fact works, so you're probably doing something else that's causing the error. I'm guessing it looks something like this

$scope.yetAnotherFunc = login.yetAnotherFunc

This will "detach" yetAnotherFunc from its context, and that is why this is not what you expect it to be.

Upvotes: 1

Christian
Christian

Reputation: 4094

Here is the solution in a fiddle:

https://jsfiddle.net/waxolunist/fcxu5eej/

HTML:

<div ng-app="app">
    <div ng-controller="LoginController">
        Get a Message:
        <button ng-click="someFunc()">someFunc</button>
        <button ng-click="anotherFunc()">anotherFunc</button>
        <button ng-click="yetAnotherFunc()">yetAnotherFunc</button>

        <div>Answer: {{answer}}</div>
    </div>
</div>

JS:

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

app.controller('LoginController', function($scope, LoginFactory) {

    $scope.someFunc = function() {
        $scope.answer = LoginFactory.someFunc();
    }

    $scope.anotherFunc = function() {
        $scope.answer = LoginFactory.anotherFunc();
    }

    $scope.yetAnotherFunc = function() {
        $scope.answer = LoginFactory.yetAnotherFunc();
    }
});

app.factory('LoginFactory', [function() {
    return {
        someFunc: function() {
            return 'abc'
        },
        anotherFunc : function(){
            var msg = this.someFunc();
            return 'Msg is '+ msg;
        },
        yetAnotherFunc : function(){
            var msg = this.someFunc();
            return 'Another msg is '+ msg;
        }
    }
}]);

But I really doubt that a factory is the right thing to use. Maybe a service would be better suited. But basically your code works.

Upvotes: 1

Related Questions