3

Ok, I'm fairly new to AngularJS, so please don't laugh if this is easy. I'm attempting to follow Todd Motto's Opinionated AngularJS Styleguide for Teams. I know it doesn't look much like it since I tried to reduce the code. I'm using Grunt to uglify my code. If I turn mangling off, it works. Otherwise, I get the error:

Error: [$injector:unpr] Unknown provider: aProvider <- a

I know this is because the name is getting mangled, so it doesn't know what to map it to, but I have no idea how/where to inject the correct name. I've tried to track it down. I think it is when we try to resolve the route, and the DataService is being injected, and because there is no inject for our DataService, I think it gets mangled.

I've tried to reduce my code down as much as possible. This also relies on angular and angular-route, as well as a file called data.json (which could be anything, it doesn't really matter). Then just run grunt debug.

Please let me know if I missed anything and thank-you for your time.

File Structure

├── data.json
├── gruntfile.js
├── index.html
└── js
    ├── app
    │   └── app.js
    └── vendor
        ├── angular-route.js
        └── angular.js

gruntfile.js

module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        uglify: {
            debugMine: {
                options: {
                    wrap: true,
                    sourceMap: true,
                    mangle: false,
                },
                files: { 'js/production.min.js': [
                    'js/app/app.js',
                ]}
            },
            debugVendor: {
                files: { 'js/vendor.min.js': [
                    'js/vendor/angular.js',
                    'js/vendor/angular-route.js',
                ]}
            }
        },
        connect: {
            server: {
                options: {
                    port: 8000,
                }
            }
        },
        watch: {
            myscripts: {
                files: ['js/app/**'],
                tasks: ['uglify:debugMine'],
            },
            options: {
                livereload: true,
                spawn: false
            },
            vendorscripts: {
                files: ['js/vendor/**'],
                tasks: ['uglify:debugVendor'],
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-connect');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.registerTask('debug',
                        'Create a debug build of the code',
                        [
                            'uglify:debugMine',
                            'uglify:debugVendor',
                            'connect:server',
                            'watch',
                        ]);
};

index.html

<!DOCTYPE html>
<html ng-app="app">
    <head>
        <meta charset="utf-8">
        <title>Mangled Names Test</title>
    </head>
    <body>

        <h2>I'm above the content</h2>
        <hr>
        <!-- Begin Content -->
        <div ng-view></div>
        <!-- End Content -->
        <hr>
        <h2>I'm below the content</h2>

        <!-- Begin Release Scripts -->
        <script src='js/vendor.min.js'></script>
        <script src='js/production.min.js'></script>
        <!-- End Release Scripts -->
    </body>
</html>

app.js

console.log('Define functions that make up app');

function DataService($http) {
    console.log('Setting up data service');
    var DataService = {};

    DataService.getData = function() {
        console.log('In DataService.getData, getting data');
        return $http.get('/data.json');
    };

    return DataService;
}

function DocumentCtrl(data) {
    console.log('In DocumentCtrl, check data');
    var self = this;
    self.data = data;
}

DocumentCtrl.resolve = {
    data: function(DataService) {
        console.log('Call DataService.getData()');
        return DataService.getData();
    },
}

function RouteConfig($routeProvider) {
    console.log('Define routes');
    $routeProvider
        .when('/', {
            template: "<h4>I'm in the content and above the data</h4><hr>{{docCtrl.data}}<hr><h4>I'm in the content and below the data</h4>",
            controllerAs: 'docCtrl',
            controller: 'DocumentCtrl',
            resolve: {
                data: function(DataService) {
                    console.log('Call DataService.getData()');
                    return DataService.getData();
                },
            }
        })
        .otherwise({ redirectTo: '/' })
}

console.log('Define module');

angular
    .module('app', ['ngRoute'])
    .factory('DataService', ['$http', DataService])
    .controller('DocumentCtrl', ['data', DocumentCtrl])
    .config(['$routeProvider', RouteConfig]);
1
  • try this in controller .controller('DocumentCtrl', ['DataService', DocumentCtrl]) Commented Sep 15, 2014 at 3:38

3 Answers 3

2

Adding mangle:false to uglify.debugVendor.options will probably fix it. If not then you probably need to compile vendor and your files together so uglify can use them in the same scope.

    uglify: {
        // ...
        debugVendor: {
            options: {
                mangle: false,
            },
        }
Sign up to request clarification or add additional context in comments.

Comments

1

Your service name is DataService therefore the declaration in your configuration should be with the same name like:

.controller('DocumentCtrl', ['DataService', DocumentCtrl])

From your sample above:

angular
    .module('app', ['ngRoute'])
    .factory('DataService', ['$http', DataService])
    .controller('DocumentCtrl', ['DataService', DocumentCtrl])
    .config(['$routeProvider', RouteConfig]);

2 Comments

Yup agree with this, OP see a note on minification here docs.angularjs.org/tutorial/step_05 alternatively use ng-annotate grunt task to do this for you.
In that style guide I linked, he talks about using resolve to get data before calling the controller, instead of getting data in the controller: github.com/toddmotto/angularjs-styleguide#routing-resolves I want it to resolve before I call the controller. And besides, even if I add the 'DataService' to my controller definition, it still breaks with mangling.
0

uglify change angularjs service name into a,b, .. . So you have to change uglify options:

options: {
    mangle: false,
},

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.