2

I want to implement the login method with AngularJS, Node and MongoDB. I have built a Restful API where I send the request.

When I try to execute the GET request this error appears at the console TypeError: UserService.logIn(...).success is not a function

Succeess doesnt exist like the $http way?

I also found this but I cannot understand how to adjust it to fit my code.

  • HTTP GET "class" actions: Resource.action([parameters], [success], [error])

  • non-GET "class" actions: Resource.action([parameters], postData, [success], [error])

  • non-GET instance actions: instance.$action([parameters], [success], [error])

Service.js

var appServices = angular.module('starter.services', ['ngResource']);

appServices.factory('UserService', function ($resource) {
    return {
        logIn: function (email, password) {
            return $resource("http://localhost:3000/users/login", {
                email: email,
                password: password
            });
        }
    }
});

Controller.js

    var apps = angular.module('starter.controller', []);
apps.controller('loginCtrl', function ($scope, $ionicPopup, $state, UserService) {

    $scope.doLogin = function doLogin(email, password) {


        if (email != null && password != null) {

            UserService.logIn(email, password).success(function (data) {
                $state.go('tabs.home');

            }).error(function (status, data) {

                var ionicPop = $ionicPopup.alert({
                    title: 'Login Failed',
                    template: 'Invalid email or password.\nPlease try again!'
                });
                console.log(status);
                console.log(data);
            });
        }
    };
});
Phil
  • 157,677
  • 23
  • 242
  • 245
Antifa
  • 377
  • 1
  • 4
  • 14
  • 1
    What's the point of using `$resource` here? Why not `$http`? – pablochan Dec 13 '15 at 21:08
  • just look here in docs: https://docs.angularjs.org/api/ngResource/service/$resource – Petr Averyanov Dec 13 '15 at 21:13
  • 4
    I think the .success() and .error() methods were deprecated. Use .then(successHandler, errorHandler) or .then(successHandler).catch(errorHandler) instead. – Shaun Scovil Dec 13 '15 at 21:15
  • @ShaunScovil i tried this but then the error is the same as the previous but with then instead of success. I think the problem is with the parameters that i pass(email,password) – Antifa Dec 14 '15 at 20:30
  • 1
    See my answer below. Typically, you would create an auth service that handles login/logout and, when the user is logged in, set a header with a token that can be passed to every other API endpoint call. So your `UserService` could be a resource configured to hit `http://localhost:3000/users/:userId` and you would call it after login, passing the current logged-in userId, like `UserService.get(userId);`. – Shaun Scovil Dec 14 '15 at 21:03
  • I just updated my answer to illustrate how you can use `$resource` if you need to. – Shaun Scovil Dec 15 '15 at 02:27

1 Answers1

5

The reason your UserService.logIn() method is not behaving as expected is, you are returning a new instance of Resource but never actually calling a method on it.

// This returns an instance of Resource, which is configured incorrectly.
// The second argument suggests that the URL has :email and :password
// parameters, which it does not. As a result, the email and password
// would be appended to the URL as query params (very insecure!).
return $resource("http://localhost:3000/users/login", {
    email: email,
    password: password
}); 

With $resource, you can define additional methods or modify the existing get, save, query and delete methods. However, this is only useful for API endpoints that support CRUD operations.

For a login call, you don't need to create a resource because you will not be performing CRUD operations. Use $http instead.

var appServices = angular.module('starter.services', ['ngResource']);

appServices.factory('authService', function ($http) {
    return {
        logIn: function (email, password) {
            return $http({
                url: 'http://localhost:3000/users/login',
                method: 'POST',
                data: {
                    email: email,
                    password: password
                },
                headers: {
                    'Content-Type': 'application/json'
                },
                withCredentials: true
            });
        }
    }
});

The above example assumes you want to pass the user credentials in the body of the request. This is okay assuming you are using SSL, but a preferred way would be to use an Authorization header. For example, Basic Auth would be a bit more secure.

UPDATE

As it turns out, methods of $resource do not return a Promise. They return an instance of the resource, with a $promise property. So, you could for example do something like this:

// Using the .save() method, which performs a POST
$resource('http://localhost:3000/users/login').save({email: 'foo@bar.com', password: 'baz'})
    .$promise.then(handleSuccess, handleError);

Still, I recommend using $http for a login endpoint. However, if you need to use $resource, have a look at this plunker.

Shaun Scovil
  • 3,905
  • 5
  • 39
  • 58