Search code examples
angularjsngresource

angular $resource receive extra information


I am using ng-resource to do ajax request. I want to send extra info besides the data.

For example, I have an article entity on my server

exports.fetchArticle = function(req, res, next) {
    var article = req.article
    return res.json({data: article, message: 'success fetch article'})
}

The reason I wrap it is that, in the case of deletion, it makes no sense to send data, I can just return res.json({data: null, message: 'deleted successfully'})

on my client side, I have:

        $scope.fetchArticle = function() {
            Article.get({articleId: $routeParams.articleId}, function(response) {
                $scope.article = response.data
                $scope.ajaxSuccess = response.message
            }, function(err) {
                $scope.ajaxError = err.data.message
            })
        }

$scope.article is not an instance of ng-resource anymore, thus I can't do further request with $scope.article, i.e. this will cause error, since $scope.article is a plain json object:

            $scope.article.$update(function(response) {...})

If I simply return res.json(article) from server, it works, but I can't send along the message.

The reason I dont generate the message from client but fetch from server is that, the error message is from server, I want to keep success message consistent with the error message.

Is there any other elegant way to send the message?


Solution

  • Assuming that all your servers responses follow this format:

    { 
        data: {/*...*/},
        message: 'some message'
    }
    

    You could use $http's transformResponse for that, so that you get an ngResource instance that is your returned object while still processing your message. For that, you need a transform-function:

    function processMessage(data, message) {
        //Do whatever you want with your message here, like displaying it
    }
    
    function transform(response) {
        processMessage(response.data,response.message);
    
        var data = response.data;
    
        delete response.data;
        delete response.message;
    
        for(var attributeName in data) {
            response[attributeName] = data[attributeName];
        }
    
        return response;
    }
    

    Then you can add this function to $http's default transfroms in the config of your app:

    angular.module("yourApp",[/* ... */])
        .config(function($httpProvider){
            //....all your other config
    
            $httpProvider.defaults.transformResponse.unshift(transform);
        });
    

    Now all repsonses from $http get transformed by this function, triggering processMessage and leaving you with a ngResource instance of the returned object.