AngularJS: How to pass values from Controller to Service Method?

daydreamer picture daydreamer · Jun 5, 2013 · Viewed 31.5k times · Source

I have a controller which is dependent on a TransactionService. One of the method is

$scope.thisMonthTransactions = function () {
    $scope.resetTransactions();
    var today = new Date();
    $scope.month = (today.getMonth() + 1).toString();
    $scope.year = today.getFullYear().toString();
    $scope.transactions = Transaction.getForMonthAndYear();
};

The TransactionService looks like

angular.module('transactionServices', ['ngResource']).factory('Transaction', function ($resource, $rootScope) {
    return $resource('/users/:userId/transactions/:transactionId',
        // todo: default user for now, change it
        {userId: 'bd675d42-aa9b-11e2-9d27-b88d1205c810', transactionId: '@uuid'},
        {
            getRecent: {method: 'GET', params: {recent: true}, isArray: true},
            getForMonthAndYear: {method: 'GET', params: {month: 5, year: 2013}, isArray: true}
        });
});

As you can see the method getForMonthAndYear depends on two parameters month and year, which are hardcoded right now as params: {month: 5, year: 2013}. How can I pass this data from my controller?

I tried injecting rootScope in TransactionService, but that did not help(meaning I do not know how to use it probably).

Also Angular ngResource documentation doesn't recommend any way to perform this.

Can someone please guide here?

UPDATE
My Controller looks like

function TransactionsManagerController($scope, Transaction) {

    $scope.thisMonthTransactions = function () {
        $scope.resetTransactions();
        var today = new Date();
        $scope.month = (today.getMonth() + 1).toString();
        $scope.year = today.getFullYear().toString();

        var t = new Transaction();
        $scope.transactions = t.getForMonthAndYear({month: $scope.month});
    };
}

and I change service method to

getForMonthAndYear: {method: 'GET', params: {month: @month, year: 2013}, isArray: true}

I look at the console.log and it says

Uncaught SyntaxError: Unexpected token ILLEGAL transaction.js:11
Uncaught Error: No module: transactionServices 

Answer

Lukus picture Lukus · Jun 5, 2013

Defining params in the resource constructor are only necessary when the call needs to have a default when none is supplied. Any param passed in to the method is appended as a query param, regardless of whether it has a default value defined. The '@' means that the params value is replaced by what gets returned in the JSON response, so your @uuid makes sense, but not your @month.

Personally, I would just create the resource like so:

$resource('/users/:userId/transactions/:transactionId',
    // todo: default user for now, change it
    {userId: 'bd675d42-aa9b-11e2-9d27-b88d1205c810', transactionId: '@uuid'},
    {
        getRecent: {method: 'GET', params: {recent: true}, isArray: true},
        getForMonthAndYear: {method: 'GET', isArray: true}
    });

Then add the query variables as needed by passing them in. (Creating special method names is fine but not necessary so showing both ways below.)

var t = new Transaction();
$scope.recentTransactions = t.$get({recent:true}) //results in /users/bd675d42-aa9b-11e2-9d27-b88d1205c810/transactions/?recent=true
$scope.recentTransactions = t.$getRecent(); //same thing as above
$scope.transactions = t.$get({month: $scope.month, year: $scope.year}); //results in /users/bd675d42-aa9b-11e2-9d27-b88d1205c810/transactions/?month=5&year=2013
$scope.transactions = t.$getForMonthAndYear({month: $scope.month, year: $scope.year}); //same as above... since no defaults in constructor, always pass in the params needed