I'm struggling to get a custom provider to work with dependencies injected into it. I'm following this blog and here is my latest version of the provider in my attempts to get it working.
define([
'angular',
'ngRoute',
'require'
], function(angular) {
return angular.module('pluggableViews', ['ngRoute'])
.provider('$pluggableViews', function() {
var providers = {};
var $injector = angular.injector(['ng']);
this.views = [];
this.registerModule = function(moduleName) {
console.log(moduleName);
var module = angular.module(moduleName);
if (module.requires) {
for (var i = 0; i < module.requires.length; i++) {
this.registerModule(module.requires[i]);
}
}
angular.forEach(module._invokeQueue, function(invokeArgs) {
var provider = providers[invokeArgs[0]];
provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
});
angular.forEach(module._configBlocks, function(fn) {
$injector.invoke(fn);
});
angular.forEach(module._runBlocks, function(fn) {
$injector.invoke(fn);
});
};
this.toTitleCase = function(str) {
return str.replace(/\w\S*/g, function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
};
this.registerView = function(viewConfig) {
if (!viewConfig.viewUrl) {
viewConfig.viewUrl = '/' + viewConfig.ID;
}
if (!viewConfig.templateUrl) {
viewConfig.templateUrl = 'views/' + viewConfig.ID + '/' + viewConfig.ID + '.html';
}
if (!viewConfig.controller) {
viewConfig.controller = this.toTitleCase(viewConfig.ID) + 'Controller';
}
if (!viewConfig.navigationText) {
viewConfig.navigationText = this.toTitleCase(viewConfig.ID);
}
if (!viewConfig.requirejsName) {
viewConfig.requirejsName = viewConfig.ID;
}
if (!viewConfig.moduleName) {
viewConfig.moduleName = viewConfig.ID;
}
if (!viewConfig.cssId) {
viewConfig.cssId = viewConfig.ID + "-css";
}
if (!viewConfig.cssUrl) {
viewConfig.cssUrl = 'views/' + viewConfig.ID + '/' + viewConfig.ID + '.css';
}
this.views.push(viewConfig);
$route.when(viewConfig.viewUrl, {
templateUrl: viewConfig.templateUrl,
controller: viewConfig.controller,
resolve: {
resolver: ['$q', '$timeout', function($q, $timeout) {
var deferred = $q.defer();
if (angular.element("#" + viewConfig.cssId).length === 0) {
var link = document.createElement('link');
link.id = viewConfig.cssId;
link.rel = "stylesheet";
link.type = "text/css";
link.href = viewConfig.cssUrl;
angular.element('head').append(link);
}
if (viewConfig.requirejsConfig) {
require.config(viewConfig.requirejsConfig);
}
require([viewConfig.requirejsName], function() {
this.registerModule(viewConfig.moduleName);
$timeout(function() {
deferred.resolve();
});
});
return deferred.promise;
}]
}
});
};
this.$get = [
'$controller',
'$compile',
'$filter',
// '$provide',
// '$injector',
'$route',
function(
$controller,
$compile,
$filter,
//$provide,
//$injector,
$route
) {
providers.$controller = $controller;
providers.$compile = $compile;
providers.$filter = $filter;
providers.$route = $route;
}];
});
});
And here is configuring the provider:
define([
'angular',
'ngRoute',
'views/nav/nav',
'scripts/providers/pluggableViews'
], function (angular) {
var app = angular.module('app', ['ngRoute', 'pluggableViews', 'app.nav']);
app.directive('navbar', function () {
return {
restrict: 'E',
templateUrl: '../views/nav/nav.html'
};
});
app.config([
'$routeProvider',
'$locationProvider',
'$pluggableViewsProvider'
], function($routeProvider, $locationProvider, $pluggableViewsProvider){
$pluggableViewsProvider.registerView({
ID: 'home',
moduleName: 'app.home',
requirejsConfig: {paths: {'home': 'views/home/home'}},
viewUrl: '/'
});
}]);
return app;
});
So far I've determined that the original article was incorrectly injecting dependencies into the .provider() instead of the $get function. I've attempted to correct this but I am still getting a "Error: [$injector:modulerr]" for my "app" module when I inject the provider. If I remove the provider from my "app" config the error goes away. So I have determined it is in fact my provider that is in error.
Update
After more debugging and isolating code. I've updated the code above to reflect my new discoveries that injected providers should leave off the "Provider" at the end of their name. I've also discovered that $injector and $provide services are causing errors. Can you not inject these services into a provider? It seems right now things are erroring when my app tries to call the registerView function. I believe the $route.resolve isn't resolving correctly.