Fix for Angular 1.3 $resource Not Stripping $ properties anymore

Version 1:

    module.config(["$httpProvider", function($httpProvider){
        $httpProvider.defaults.transformRequest.unshift( function(data){
            if (typeof data == "object"){
                var remove = [];
                for (var i in data) { if (i.indexOf("$") == 0 && i.indexOf("$$") == -1 && typeof(data[i]) != "function") remove.push(i); }
                remove.forEach(function(k){ delete data[k]; });
            }
            return data;
        });
    }])

Version 2:

    module.config(["$httpProvider", function($httpProvider){
        $httpProvider.defaults.transformRequest.unshift( function(data){
            if (typeof data == "object"){
                var copy = angular.copy(data);
                var remove = [];
                for (var i in copy) { if (i.indexOf("$") == 0) remove.push(i); }
                remove.forEach(function(k){ delete copy[k]; });
                return copy;
            }
            return data;
        });
    }])

Let's examine. There's a bit going on here.

$resource registers its own transformRequest functions before ours is defined, but I want mine to load first.

$httpProvider.defaults.transformRequest.unshift

Unshift puts my method at the beginning. The data at this point is an object, whereas if I were to push it to the end, after the $resource transformRequest function, I get a string. It seems a bit more efficient to work with the object first, than to allow $resource to JSON.stringify the data, then for me to load it up through JSON.parse after.

The main difference between Version 1 and Version 2 is that I copy the object in Version 2 so I can delete any property that begins with $, whereas in Version 1 I skipped deleting functions and properties that Angular needed, but then the reference objects were deleted from my actual object, so the list view got messed up, because it's looking for those properties.  So Version 2 is correct.

I add this to my global module, the one that gets bootstrapped to <html>, so that it only has to be registered once, like so:

;(function(angular){
    var module = angular.module("global.app", [...]);
    module.config(["$httpProvider", function($httpProvider){
        $httpProvider.defaults.transformRequest.unshift( function(data){
            var copy = angular.copy(data);
            if (typeof copy == "object"){
                var remove = [];
                for (var i in copy) { if (i.indexOf("$") == 0) remove.push(i); }
                remove.forEach(function(k){ delete copy[k]; });
            }
            return copy;
        });
    }])
})(angular);

And then bootstrap it 

;(function(angular, document){
    angular.element(document).ready(function(){
        angular.bootstrap(angular.element("html"), ["global.app"]);
    })
})(angular, document);

Simple

 

blog comments powered by Disqus