0

I tried to write factory method in Angular JS:

.factory('FriendsFactory', function(){

            var friend = {};

            friend.delete = function(id) {
                notificationsModal.show('danger', messages_info[86]);
                notificationsModal.confirm(function() {
                    this.deleteAjax(event, id, type);
                })
            }

            friend.deleteAjax = function (event, id, type){
                var target = angular.element(event.target);
                var request = $http({
                    method: "POST",
                    url: "/subscribe/deletesubscriber",
                    data: $.param({ id : id, type : type }),
                    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
                });

                request.success(function () {
                    target.closest('.notif-item').remove();
                    $scope.counter--;
                });

                request.error(function () {
                    // TODO
                });
            }

            return friend;
        })

This code has two methods: friend.delete() also friend.deleteAjax()

Calling functions from Factory:

.controller('FriendsController', ['$scope','$http', 'friendsFactory', function($scope, $http) {
    $scope.deleteUser = function (idUser) {
        friendsFactory.delete(idUser);
    }

}])

I need decrement variable $scope.counter in friend.deleteAjax() ajax response, regardless controller from was called factory. I can do duplicate in each controller:

$scope.counter = 10; and after call factory, but it is not good

2 Answers 2

2

Although the answer suggested by @JBNizet is absolutely correct but if you are bound to use the code in the way it is, then you can do two things. First is to simply pass the $scope from controller to service call (which is not a cleaner approach is not recommended):

$scope.deleteUser = function (idUser) {
    friendsFactory.delete(idUser, $scope);
}

And you can use the scope inside the factory.
The second option to use current controller's scope to root scope and then use this in the factory.

In your controller

$scope.deleteUser = function (idUser) {
    $rootScope.callingControllerScope = $scope;
    friendsFactory.delete(idUser);
}

In your factory

friend.deleteAjax = function (event, id, type){
     console.log($rootScope.callingControllerScope.counter);
     // your code
}

And you also need to fix your dependency injection:

.controller('FriendsController', ['$scope','$http', 'FriendsFactory', function($scope, $http, friendsFactory) {
    $scope.deleteUser = function (idUser) {
        friendsFactory.delete(idUser, $scope);
    }
 }]);
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. I tried: .controller('FriendsController', ['$scope','$http', 'friendsFactory', function($scope, $http, $friendsFactory) { $scope.deleteUser = function (idUser) { friendsFactory.delete(idUser, $scope); }}]) and got error: Error: [$injector:unpr] FriendsController
You are injecting FriendsFactory with the wrong case. Change it as: .controller('FriendsController', ['$scope','$http', 'FriendsFactory', function($scope, $http, friendsFactory) { $scope.deleteUser = function (idUser) { friendsFactory.delete(idUser, $scope); }}])
I've also modified the answer with the fixed dependency injection. The name of the factory or any service needs to be exactly the same as what is defined in the factory name. So you have defined friendsFactory instead of FriendsFactory (camel case).
2

You're doing many, many things wrong:

Using friendsFactoryinstead of FriendsFactory:

.controller('FriendsController', ['$scope','$http', 'friendsFactory'
                                        here --------^

Forgetting to declare friendsFactory as an argument of the controller function:

.controller('FriendsController', ['$scope','$http', 'friendsFactory', function($scope, $http) {
                                                                                  here ----^

Accessing an undefined $scope variable in the service:

$scope.counter--;
^--- here

Doing DOM manipulation in a service...

The service responsibility is not to manipulate the DOM and the controller scope.

The DOM should be modified using directives in the html template.

The controller scope should be managed by the controller, not by the service. Return the promise request from the deleteAjax() function, and let the controller register a success callback, rather than doing it in the service. This callback will then be able to access the controller scope.

Note that most errors are basic JavaScript error that should be signalled by a good JavaScript editor, or at least by looking at errors in the console of your browser.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.