Mismatched anonymous define() in requirejs/angular - angularjs

Yes, I know this has been asked ad infinitum here, and I already know the general rule that when using requirejs, everything that calls define() must be loaded through a single script tag as in:
<script src="js/lib/require.js" data-main="js/main"></script>
but I find myself in a position where the general advice offered with respect to this common error is not sufficient for solving my particular problem, which on the surface seems pretty simple.
I am working on an angular, requirejs, and WinJS (just to keep things interesting) app, and have run into a problem with this error. My main html file does indeed load several other JavaScript source files using separate script tags but none of them call define(). I checked. Twice. Okay, three times. All other JS source files in the app are loaded through a single script tag similar to the above. Yet I still get this error.
I tried giving each of my app modules a requirejs identifier:
define('myModule', ['dep1', 'dep2', etc.], function(dep1, dep2) {
return angular.module('app.mymod', ['winjs', etc.]);
});
but with this approach angular modules that depend on the angular module defined as above cannot resolve that dependency (although requirejs is now perfectly happy).
The three JS files being loaded outside requirejs are:
<script src="//Microsoft.WinJS.2.0/js/base.js"></script>
<script src="//Microsoft.WinJS.2.0/js/ui.js"></script>
<script src="js/lib/dynamic-content-shim.js"></script>
Where the latter patches the WinJS runtime to allow dynamic content creation. The WinJS runtime does actually expose a define function in its own namespace, but it is completely unrelated to requirejs.
So what gives?

Related

Reference node_module after running browserify

I found a nodejs module that I would love to be able to include in my Angular app. I read around and saw that I can do this by running browserify on it. After doing this, I have referenced the new file in my html, but I don't know what to do after that. Where do I need to reference it to get it in angular scope? Here is the github repo I want to be able to access
https://github.com/whatadewitt/yfsapi
After I browserify the files in the node_modules folder, I have one big js file. The usage for this in Node is
var YahooFantasy = require('yahoo-fantasy');
// you can get an application key/secret by creating a new application on Yahoo!
var yf = new YahooFantasy(
Y!APPLICATION_KEY,
Y!APPLICATION_SECRET
);
It seems it needs a require here, but isn't that the whole reason I ran browserify in the first place? What am I missing here?
From the Browserify website:
Browsers don't have the require method defined, but Node.js does. With
Browserify you can write code that uses require in the same way that
you would use it in Node.
The point of Browserify is to give you a module system in the browser and to allow you to require files. It's incredibly useful and allows you to easily include Node modules and modularize your own app.
To use the Node module you're referencing in an Angular app, you would do basically exactly what the demo shows in either a controller or service. Personally, I'd probably recommend creating a service that wraps the Node module and exposes methods to interact with the Yahoo Fantasy servers; I probably wouldn't put it on $scope unless you absolutely had to for some reason.
Here's some pseudo-ish code:
var yf = require('yahoo-fantasy');
function YFantasyService (<dependencies>) {
this.someMethod = function () {
return yf.doStuff();
}
}
YFantasyService.$inject = [<dependencies>];
module.exports = YFantasyService;
Register your service (this is how my app is structured...there are plenty of other ways to write and register services but you get the idea):
angular.module('YFantasyApp', [<dependencies>])
.service('YFantasyService', require('./YFantasyService'));
Then inject it into other services and controllers and do whatever you want with it.
If you want to build a bundle that contains yahoo-fantasy - so that you can use it with minimal changes to your existing code - you can use the Browserify API:
var browserify = require("browserify");
browserify()
.require("yahoo-fantasy", { expose: "yahoo-fantasy" })
.bundle()
.pipe(process.stdout);
That will generate a bundle that contains yahoo-fantasy module and all of its dependencies and will expose a global require function that you can call to access said module:
<!doctype html>
<html>
<head>
<title>so-40120643</title>
</head>
<body>
<script src="./bundle.js"></script>
<script>
console.log(require("yahoo-fantasy"));
</script>
</body>
</html>
If you want to use a different name for the global require function, you can use Browserify's externalRequireName option.

Electron + AngularJS Views not found

I am trying to develop a desktop application using Electron. I am also using AngularJS.
The problem I am running into is that when I create a custom directive, and load a templateUrl, the view doesn't load and the console says it doesn't exist. Yes, the path is correct, I am sure of it.
The problem is that the application is already running index.html, so it can't load the second file. Needless to say, I am not experienced enough to solve this problem on my own.
I know that Electron uses node on the backend, so I suppose setting routes and/or setting a path to my static files might resolve the problem, but I don't know how to do it.
I have searched the whole web for a solution, but I couldn't find a clear answer.
One way you could easily do it, is by adding your template as an inline template on the angular side, for example in your index.html:
<script type="text/ng-template" id="temp1.html">
....
</script>
Then you can reference it from your directive, like templateUrl: temp1.html.
Otherwise, you could also use a module bundler. Webpack has a ng-template loader which does that for you. Gulp and Grunt also have equivalents
Another thing to try, if you need to reference paths from the js side, is to use __dirname nodejs variable. Here an example

Angular Dynamically Inject Module Dependency

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.

How does browserify work with angular based app?

I was mess around this for a couple of days. I was trying to get browserfiy to work well with angular based app. I have tried following options but still cannot decide on a better way to do it, it will be appreciated if anyone can give any suggestion on this.
Option 1
Bundle all angular related libs, like angular, angular-animate, angular-ui-router, etc into vendor.js by using bundle.require
Bundle all app reated source files into app.js by using bundle.external
That works fine in dev environment, all modules in vendor.js could be required from app.js
But it crashed in prod environment. The minified angular files are not all CMD. Although I can browserify-shim angular.min.js and bundle.require angular-ui-router.min.js, it's kind of cubersome to do this file by file.
Option 2
Leave all angular libs into <script> and only output bundle for app files. That means in app.js, I have to refer to angular as a global var which is not good.
So what's the best practise to do this?
Even if you do require() angularjs, it still exposes the angular namespace in the context of its environment (Window object for browsers). What I usually do is simply put all angularjs modules dependencies (e.g. ui.router, ngResource and etc) below the bundled(browserified) javascript where your angularjs application resides. In my case, I use gulp-useref to concatenate all the script provided by the gulp-inject tags(this includes scripts bundled by browserify).
As you may have noticed below, the bower components(bower:js tag) are added below the bundle(inject:js tag). Since requiring the angular module will attach the angular object in the window object, then any components external to browserify can access window.angular.
The answer I provided is somehow similar to option 2 but without the disadvantage of referring angular as a global variable within your browserified code.
e.g.
<!-- build:js({./.tmp,./}) js/index.js -->
<!-- inject:js -->
<!-- endinject -->
<!-- bower:js -->
<!-- endinject -->
<!-- endbuild -->
UPDATE:
I've create a github repo that resembles the answer provided above. Try to clone it, and see what you can do with it.

Angular Basic Load Order

In a very basic Angular app we have
<head>...
<script src="app.js"></script>
<script src="maincontroller.js"></script>
App defines the app module, and controller then hangs off app as app.controller("MainController..") If the order of the two scripts is reversed, the app will throw an error "app is not defined".
Is there a way around this load order dependency? My fear is that as it becomes more complex, I will get script order dependencies. And perhaps I might want to load my scripts async as well.
Thank you.
See, for example, this plunker: http://plnkr.co/edit/kqVqTHxl4tc6mIV5bDbQ
I've defined SomeService in an own file, svc.js. I've defined the module and the main controller in app.js. And even though the MainController depends on that service that "loads later", the dependency is figured out, and injected. All you should worry about is: put the module definition first.
Also: Don't store the application inside a global variable called app, instead, use angular.module with the name of the module to retrieve a reference to it:
angular.module('SomeModuleName').controller(...)
Any kind of global variables are generally not a good practice.
Look at using Angular and Browserify or Angular and RequireJS. Browserify and RequireJS are module loaders that let you keep 1 script reference in your index.html.
Browserify is based on a build step that will bundle all your JS into 1 file.
RequireJS is an Asynchronous Module Definition (AMD) loader, that can load your files asynchronously.

Resources