0

I have created an app based on ng-boilerplate. All works just fine. However, now I am coming close to deployment, I want to compile and minify the code. This is straighforward enough using grunt compile, but of course the app breaks when minified. I didn't expect anything less!

I have injected dependencies into my controllers like this:

var appCtrl = app.controller('AppCtrl', function AppCtrl($scope, $rootScope, helpService, userService, menuService, $location) {... body ...});

appCtrl.$inject = ['$scope', '$rootScope', 'helpService', 'userService', 'menuService', '$location'];

I have also tried it like this:

 var appCtrl = app.controller('AppCtrl', ['$scope', '$rootScope', 'helpService', 'userService', 'menuService', '$location',
 function AppCtrl($scope, $rootScope, helpService, userService, menuService, $location) {... body ...}]);

All I ever get is an error like this: Error: Unknown provider: aProvider <- a

I have also looked at my services and injected the dependencies in a similar way to the second method above, but then I started getting errors in the program even when it was not minified. It was telling me $q has no method defer()!

app.factory('checkAuth',  ['$q', '$location', '$filter', '$rootScope', function ($q, $location, $filter, $rootScope) {...body...}]);

My question is, what am I missing? Am I doing the dependency injections correctly? Is there somewhere else needing DI?

Thanks!

EDIT: Just found this: Angular.module minification bug

It hasn't completely fixed the problem... I now get the error:

TypeError: Object #<error> has no method 'slice' 

but at least this is away from Error: Unknown provider: aProvider <- a :-)

Community
  • 1
  • 1
Craig Morgan
  • 942
  • 2
  • 11
  • 27

2 Answers2

4

Your second approach is using angular's inline annotation method, and that should be able to be minified correctly.

Other approaches will not work because of how Angularjs handles it's dependency injection - it will look at the parameter's name to determine the provider. Your minifier will change the parameter name from $scope to a, and Angjuar will try to find a provider for a. The inline style fixes this at the cost of more typing and a bit more maintenence. (There's a tool that will alter your angular code so that it can be minified by grunt here: https://github.com/btford/ngmin )

I would expect that your issue is that not all of your controllers or modules were altered to use the inline style, and you continued to get the error. Make sure you change all of it - read up on Angularjs DI, especially inline annotation.

Philip Rieck
  • 32,368
  • 11
  • 87
  • 99
0

OK - Fixed it: I changed the filter to return text rather than a boolean value like this:

function orgFilter(item, args) {
    if ((args.searchString !== "" && item["strName"].indexOf(args.searchString) == -1) &&
        (args.searchString !== "" && item["strShortName"].indexOf(args.searchString) == -1) &&
        (args.searchString !== "" && item["strCode"].indexOf(args.searchString) == -1)
        ) {
//            return false;
        return 'continue_coreloop';
    }
//        return true;
    return 'add_result';
}

... and then changed the compileFilter() function to match the text

  var filterBody = filterInfo.body
      .replace(/return \'continue_coreloop\'[;}]/gi, "{ continue _coreloop; }")
      .replace(/return \'add_result\'[;}]/gi, "{ _retval[_idx++] = $item$; continue _coreloop; }")
      .replace(/return ([^;}]+?);/gi,
      "{ if ($1=='add_result') { _retval[_idx++] = $item$; }; continue _coreloop; }");

Uglify doesn't change the text values so the match will still be true.

Craig Morgan
  • 942
  • 2
  • 11
  • 27