-
Notifications
You must be signed in to change notification settings - Fork 38
Added the ability to specify a custom module to create the injector #11
Conversation
|
Hey thanks a lot! This seems like a very cool feature. I will merge this soon and release a new version in the next days. |
Added the ability to specify a custom module to create the injector
|
Thanks again, i like this feature very much and can also use this in my current project! :) I'll update the docs and publish a new release. Sorry for the delay... |
|
now available via bower in version 0.1.0: https://github.com/philippd/bower-angular-deferred-bootstrap/releases/tag/v.0.1.0 |
|
Awesome! Thanks for accepting, I'll be updating my project to use the new bower version and not my fork :) |
|
First of all @Shepless, thanks very much for putting the time into this feature - it really did seem like a necessity to have the injector format built into the resolve items. <!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script src="components/angular/angular.js"></script>
<script src="components/angular-deferred-bootstrap/angular-deferred-bootstrap.js"></script>
<script>
var app = angular.module('app', ['app.services']);
angular.module('app.services', []);
app.factory('TestService', function () {
return {
log: function (message) {
console.log(message);
}
}
});
deferredBootstrapper.bootstrap({
element: document,
module: 'app',
injectorModules: 'app.services',
resolve: {
LOAD_CONFIG: [
'TestService',
'$timeout',
function (TestService, $timeout) {
return $timeout(function () {
TestService.log("this happens")
}, 1000)
}
]
}
})
</script>
</body>
</html>The error is: The version of angular I am using is 1.2.19 and the version of this script is the current (0.1.0) |
|
Hi @marksyzm |
|
Ah, simple mistake... okay, it wasn't actually that error now that I look at it. With this: <!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script src="components/angular/angular.js"></script>
<script src="components/angular-deferred-bootstrap/angular-deferred-bootstrap.js"></script>
<script>
angular.module('app', ['app.services']);
var app = angular.module('app.services', []);
app.provider('TestService', function () {
return {
log: function (message) {
console.log(message);
}
}
});
deferredBootstrapper.bootstrap({
element: document,
module: 'app',
injectorModules: 'app.services',
resolve: {
LOAD_CONFIG: [
'TestService',
'$timeout',
function (TestService, $timeout) {
return $timeout(function () {
TestService.log("this happens")
}, 1000)
}
]
}
})
</script>
</body>
</html>I get this: Which is actually the dreaded "missing ngLocale" error you get when a module can't be found and returns an Any ideas? I've been trying to solve this with no joy. |
|
I created a working plunker with your example here: http://plnkr.co/edit/CrMY8uGu7eKOIW6ApVNz?p=preview The problem was that you injected $timeout but did not specify the angular core module |
|
I've got it... I made an error just then again and should have put Edit: Ha! I just worked it out when you did! Yeah, I would specify that it is either required or a default module. |
|
Hi @marksyzm The error generated is because your provide does not implement a app.provider('TestService', function () {
this.$get = function () {
return {
log: function (message) {
console.log(message);
}
}
};
});Once this is fixed it will fall over because you aren't explicitly requiring the var app = angular.module('app.services', ['ng']);Full working source: angular.module('app', ['app.services']);
var app = angular.module('app.services', ['ng']);
app.provider('TestService', function () {
this.$get = function () {
return {
log: function (message) {
console.log(message);
}
}
};
});
deferredBootstrapper.bootstrap({
element: document,
module: 'app',
injectorModules: 'app.services',
resolve: {
LOAD_CONFIG: [
'TestService',
'$timeout',
function (TestService, $timeout) {
return $timeout(function () {
TestService.log("this happens")
}, 1000)
}
]
}
});I'm 50/50 on whether we should make the deferred bootstrap inject |
|
In which case I would specify that information about the |
|
Yeah definitely - what are your thoughts @philippd? Do you think we should auto inject |
|
Ignore that provider user error... I was just trying out other stuff and accidentally left it in |
|
@Shepless yes, I'd suggest to do this. I usually do not list I think it's too easy to make a mistake like this and don't see a problem with always adding the module. Is there a good reason not to do it? |
|
My personal view on this is that modules are supposed to be small, re-usable and isolated areas of code and should be self sufficient e.g. if I ran I'd prefer to have someway of checking if |
|
Maybe throw an error to suggest including the module rather than auto including it? |
|
@marksyzm Yeah thats the approach I'm thinking, however it might not actually be an error. The user might not want to include angular.module('myMod', [])
.factory('myService', [function () {
return {
isValid: function (foo) {
return (!!foo);
}
}
}])Theres no need for any |
|
I was just thinking if the service they were injecting was from |
|
It's a tricky one! We don't want the module to be too restrictive but we also want it to be transparent as to why the injector fails! |
|
Another thing I spotted is that is that, unlike with native angular, you can't just put the deferred bootstrapper in and expect it to assume custom modules will be loaded before bootstrapping starts. This is obviously solvable with the standard use of checking for the document |
|
Another "gotcha" probably worth mentioning is that the service you instantiate is initialised separately to when it is used in the app, so any changes you make to it in the deferring section will be a separate object to the app. |
|
After having a look at the angular.js |
Yes, this is how it works because a new injector will be created as soon as all promises in the resolve object are resolved. I'll update the docs and add a note for that. |
|
@philippd To get around that issue with new injectors and whatnot, I just passed the services with their values into an object and updated the newly instantiated singletons in |
|
@marksyzm the |
I have made a few alterations that allow the config to take an optional
injectorModulesmember. This will allow users to decide which module the deferred bootstrap should use and allows the injection of custom services.I personally have a use case where I want to use one of my existing services to get configuration at bootstrap time, however this service is also used in other areas of the app, saving me from duplicating code. An example is below:
The
injectorModulesoption can also take an array of modules so if you have multiple services spread across different modules you can also inject them:As I mentioned previously this is a completely optional config member and if not included does not impact existing functionality.
You may also notice that this change uses the
injectorto instantiate theresolveFunction. This gives the added benefit of being able to specify dependency injection in the various ways angular itself allows, for example:Which in turn allows this bootstrap code to also be minified, something that is not currently available.
I have included two new units tests to cover this new functionality. I hope it meets the requirements.
Cheers.