I am using 'Modernizr' for detecting mobile devices.I have created 'touchevent.js' file for the mobile devices
In touchevent.js
`var touchApp = angular.module('ngTouchEvent', [])
In script.js
'var app = angular.module('myApp', [ 'ngTouchEvent' ]);
now I want to load touchevent.js only in mobile devices using modernizr.
I am using
Modernizr.load('touchevent.js');
I am facing problem like
[$injector:modulerr] Failed to instantiate module myApp
in other than mobile device.
I dont want to load touchevent.js in desktop.Can I have solution for multiple dependacy
Actually Modernizr is an javascript object which you can use directly in any angular controller or directive without specifying any dependency on angular app. You can create an provider like this to use Modernizr in controller or directive like this:
angular.module('myApp').provider('Modernizr', function() {
this.$get = function() {
return Modernizr || {};
};
});
Modernizr.mq()
You can have a look at this project which offer a base project for using AngularJS with RequireJS to load on demand the required js files.
https://github.com/tnajdek/angular-requirejs-seed
If your application is huge, it might be useful, otherwise it can be overkill because just the fact of using AngularJS reduce the amount of code to be written.
Hoping it will be helpful
Related
I want to use $templateCache service to add some html into the cache. In Angular documentation example, it only shows the case of using it in run:
var myApp = angular.module('myApp', []);
myApp.run(function($templateCache) {
$templateCache.put('templateId.html', 'This is the content of the template');
});
However, when I am trying to add some templates through myApp config, there seems to be injector error. Is there a way to use templateCache not in RUN?
Thanks
run is the correct place to use the $templateCache. Since $templateCache is a service, it's not accessible in the configuration phase, because it hasn't been created yet. config is used to configure services (like $templateCache) using their providers. You can only inject providers to config.
My opinion is that, most of the time, you shouldn't be writing code that accesses $templateCache directly at all. What you should be doing is using a build system such as gulp and a plugin such as gulp-angular-templatecache.
Then your templates are simply a bunch of .html files, your editor recognises them as html and does the appropriate linting while you edit, and all you have to do is ensure your app declares a dependency on the template module.
So the code you gave above would become:
var myApp = angular.module('myApp', ['myappTemplates']);
and the use of $templateCache inside .run() is pushed down to automatically generated code that you never see.
I've developed a commenting plugin for Umbraco that uses angular. As such the main angular app for the site has to inject the comment systems module for it to work.
E.g.
var theirSite = angular.module('someApp', []);
Injected
var theirSite = angular.module('someApp', ['theCommentSystemModule'];
In my comment system,
angular.module('theCommentSystemModule']....;
Is there any way my module can automatically detect the angular app and inject itself without the code for the site having to be updated? I want it to just work with nothing but the script link.
For Example: say these are the scripts
<script src="...angular.js">
<script src="...services.js">
<script src="...directives.js">
<script src="...commentsPlugin.js">
<script src="...theirApp.Js">
So what I basically need, is some kind of callback from angular when the app is being bootstrapped, so I can inject the comment systems module into the app as a depedency module so that it will initialize in their bootstrap layer.
Or maybe, alternatively, I bootstrap the page myself in the plugin for itself? Can there be two apps running at once, e.g. if I bootstrap and their app also bootstrap's .
It can be done by using undocumented requires module property. This way new dependencies can be added to the module after it was defined but before it was bootstapped.
Since 'ng' is the only known and defined module ATM (it also has already defined requires array), tamper it:
angular.module('ng').requires.push('theCommentSystemModule');
Though it is more appropriate to let the users load the module by themselves.
What issues might I experience in having two different versions of AngularJS loaded into one page?
Obviously this seems like a stupid thing to do, but my use case is a page that uses AngularJS incorporating a third-party component that drags in its preferred version of AngularJS.
Update:
Found some info:
https://groups.google.com/forum/#!msg/angular/G8xPyD1F8d0/u1QNDNvcwW4J
https://github.com/angular/angular.js/pull/1535
Angular is really not prepared to co-exist with other version. But it's feasible.
First of all load angular library and make sure that before loading window.angular is empty:
<script src="vendor/angular/1.2.0/angular.min.js"></script>
<script src="app/app2.js"></script>
<script>
var angular2 = angular;
window.angular = null; // here we're cleaning angular reference
</script>
<script src="vendor/angular/1.0.5/angular.js"></script>
<script src="app/app1.js"></script>
<script>
var angular1 = angular;
</script>
Note that each application (app1.js, app2.js) for each version of angular should be loaded immediately after loading angular library.
Each JavaScript file of the application shoud be wrapped in self executing function (function(angular) { ... })(angular). Look at the example of app2.js:
(function(angular) {
angular.module('myApp2', []).
controller('App2Ctrl', function($scope) {
$scope.$watchCollection('[a, b, c]', function() {
console.log(angular.version.full);
});
});
})(angular);
Note that here I'm using $watchCollection which is only available for angular 1.2.x. By providing scope of anonymous function for each file you are forcing application to reach angular property instead of window.angular property.
Finally you have to bootstrap the application using manuall method:
<body>
<div id="myApp1" ng-controller="App1Ctrl">
</div>
<div id="myApp2" ng-controller="App2Ctrl">
</div>
<script>
angular1.bootstrap(document.getElementById('myApp1'), ['myApp1']);
angular2.bootstrap(document.getElementById('myApp2'), ['myApp2']);
</script>
</body>
Working plunker here. After running please check console window to see logged versions of angular used.
Great question! Like you, we were unable to uncover much on this topic...we are in the process of deploying a version of Angular with our product which will be embedded within client websites that could also have Angular already loaded.
Here is what we have done:
Modify the Angular source - do not use "window.angular" or "angular" in your implementation, choose some other variable or object property to house it. If you do use "window.angular" and/or "angular", it could break both applications if the versions are different.
Rename all delivered objects (directives, etc); otherwise, the other version of angular could attempt to process your directives.
Rename all CSS classes used by Angular (ng-cloak, etc). This will allow you to style your version of Angular separately from the other version.
Manually bootstrap your application, as described by 'kseb' above.
If you are going to completely name space AngularJS as I have described here, take care to not do a global search and replace because angular does need a "window" reference for registering events, and a few other places.
I just finished doing this at work and I am in the process of testing. I will update this answer with my results.
Matt Burke describes a process to wrap the Angular JS libs in a function to create a closure. Downside is that you cannot load Angular via a public CDN as you have customized the download.
http://www.mattburkedev.com/multiple-angular-versions-on-the-same-page/
Angular 2 will provide a new router with similar features to UI router, but that will also allow to have some routes in Angular 1 and others in Angular 2.
This router is currently being backported to Angular 1, see here a presentation from the developer of the new router explaining how this will work.
The idea behind a common cross-version router with support for both version is to help users upgrade from Angular 1 to Angular 2.
I am new to AngularJS (reading docs for a week or so) so bear with me :) I am trying to expose some 3rd party library (JayData) functionality to AngularJS controllers via the DI/service infrastructure.
Creating a service is a straightforward thing, as long as you can manage to create your own module for this, and set ng-app to that module.
var mod = angular.module('myModule', [], function ($provide) {
$provide.factory('$data', ['$scope', function (sc) {
return $data;
}]);
});
<html ng-app='myModule'></html>
In my case developers will create their own app/startup module, or will use the "default ng app" without specifying an kind of module names like <html ng-app="".
How can I register a service that is globally accessible like the built-in services like $scope or $http?
You can add components to the ng module, which is the default module, with angular.module("ng").service(...). As mentioned in the comments, this is a bad idea for several reasons, most prominently that the Angular team might provide a service with the same name later.
For reference, the preferred way is to define your own module such as myAwesomeDataModule and add it as a dependency in other modules: angular.module("myModule", ["myAwesomeDataModule"]).
it seems that from angular's point of view the order of registering of a service provider and the module configuration code is important: in order for the configuration code to find the provider, the provider should be registered before.
This was a total surprise for me, as I thought that angular first processes all provider registrations, to make them available for DI, and then calls config callbacks, like this:
module.config(function(myServiceProvider) {...});
Please see here a very short test that demonstrates the problem. It fails on "unknown provider", you can see it in the JS console: http://plnkr.co/edit/jGJmE2Fq7wOrwubdlTTX
Am I missing anything here? Is it an expected angular behavior?
Thanks.
Looks like this behavior has changed in more recent versions of Angular (not sure when exactly). I modified your Plunker to point from 1.0.7 to 1.3.0 and it worked without error as you had originally expected.
Similar example of code that works:
var myModule = angular.module('myModule', []);
myModule.config((myServiceProvider) => {
});
myModule.service('myService', () => {
});
Running a config for a provider before the provider is registered with the module should work just fine as you were expecting.
Reference
For reference, this reported issue appears to be the one to have fixed it: https://github.com/angular/angular.js/issues/6723
The Angular documentation for module state that:
Recommended Setup
While the example above is simple, it will not scale to large applications. Instead we recommend that you break your
application to multiple modules like this:
A service module, for service declaration
A directive module, for directive declaration
A filter module, for filter declaration
And an application level module which depends on the above modules, and which has initialization code.
As you are using a single module that you call app, you are creating a dependency between that module's config and declaration of a provider. What you should have done is to place all your providers into a separate module, such as:
var appr = angular.module('appr', [])
.provider('myService', function() {
this.$get = function() {};
})
Then you declare the dependency of your app using:
var app = angular.module('plunker', ['appr']);
Check out the updated Plunker: http://plnkr.co/edit/Ym3Nlsm1nX4wPaiuVQ3Y?p=preview
Also, instead of using the generic provider, consider using more specific implementation of provider such as controller, factory or service. Take a look at Module API documentation for more detail.