Uncaught Error: [$injector:modulerr] Failed to instantiate module with LABJS - javascript

I keep getting this error when loading my Angular app. In Chrome a couple refreshes and my app will run but IE and FF is a no go.
The error links me to this error page but I don't really understand what it says.
I am loading my app using LabsJS including the controllers and service.
// spAppLoader.js
$LAB
.script("../js/app.js").wait()
.script("../js/controllers/userCtrl.js")
.script("../js/controllers/groupCtrl.js")
.script("../js/controllers/siteCtrl.js")
.script("../js/services/userServices.js")
.script("../js/services/groupServices.js")
.script("../js/services/siteServices.js")
Markup:
<div id="mdContainer" ng-app="spApp" ng-cloak>
...
</div>
<script type="text/javascript" src="../js/spAppLoader.js"></script>
I wanted to post more code but I don't know where to start and with angular everything is in multiple files. I uploaded it through github.

You should manually bootstrap your app because you use an asynchronous script loader:
$LAB
.script("../js/app.js").wait()
.script("../js/controllers/userCtrl.js")
.script("../js/controllers/groupCtrl.js")
.script("../js/controllers/siteCtrl.js")
.script("../js/services/userServices.js")
.script("../js/services/groupServices.js")
.script("../js/services/siteServices.js")
.wait(function(){
var root = document.getElementById('mdContainer')
angular.bootstrap(root ,['spApp']);
})
What is bootstrapping?
angular.bootstrap(root ,['spApp']); is the same as <div id="mdContainer" ng-app="spApp"> only the last one would automatically initialize your app when DOMContentLoaded event occurs.
When using a script loader, DOMContentLoaded event might happen before all scripts are loaded, so you must wait for all your module scripts and then bootstrap your application manually.
In your case, chrome probably cached your scripts so after few refreshes the DOMContentLoaded event happened after all scripts were loaded.
From the docs:
Automatic Initialization
Angular initializes automatically upon DOMContentLoaded event or when the angular.js script is evaluated if at that time document.readyState is set to 'complete'. At this point Angular looks for the ng-app directive which designates your application root...
Manual Initialization
If you need to have more control over the initialization process, you can use a manual bootstrapping method instead. Examples of when you'd need to do this include using script loaders or the need to perform an operation before Angular compiles a page.

This error usually means angular can't find an object you are trying to inject into a controller or some other injectable function. After quickly looking through your code, my guess is that there is a problem with the way the files are being loaded, as you are referencing spApp from multiple files.
What I usually do is move separate files into their own modules, and then require other modules as needed. For example, instead of starting the userService like this:
spApp.factory('userService', function(){
put it into its own module
angular.module('spApp.services.user', [])
.factory('userService', function(){
Then whenever you need to use the userService in another module, add it as a requirement. Eg:
var spApp = angular.module('spApp', ['spApp.services.user']);

Related

Third party packages are getting undefined even after script loaded successfully

Third-party packages are getting undefined even after the scripts loaded successfully.
We are loading 4 third-party packages dynamically(Using CDNs) in React. We show a loading view when these CDNs are fetching, only after all the CDNs are loaded successfully then we show a UI using these packages.
Packages are
jquery-3.0.0.min.js
d3.v2.min.js
jquery.jsPlumb-1.3.10-all-min.js
jquery-ui.min.js
We are loading the scripts in the above order respectively.
Even after all the scripts loaded we are getting the below errors for some users.
$.isArray is not a function.
d3 is not defined
$('#' + domRootID).resizable is not a function.
Even if we are writing our logic after ready like below, the issues aren't resolved
$(document).ready(() => {
// Change the state variable to show the UI.
})
We aren't able to understand why we can't access third-party variables after the scripts are loaded.
Can someone suggest a solution for this?

Dojo timing issue with dijit/registry and dojo/domReady

I am working on a one-page application in Dojo which submits forms via ajax and returns parses the return value before rendering the page. When I go about this I end up with a timing error.
When the following code is included via a script tag, it logs undefined:
require(["dijit/registry", 'dojo/domReady!'], function(registry){ console.log(registry.byId('my-id')) });
When I paste it in the console, I get the expected dijit widget.
I suspect that the problem is that this is firing before the page is rendered. Is there an easy way to ensure that this happens after the current document has been fully parsed and included in the main window?
May be you should try, to add Parser and call the Parser.parse() before trying to access the widget.
This is from Dojo documentation
Note that waiting for dojo/domReady! to fire is often not sufficient
when working with widgets. Many widgets shouldn’t be initialized or
accessed until the following modules load and execute:
dojo/uacss
dijit/hccss
dojo/parser

Dynamically loaded AngularJS application

I'm looking to integrate an AngularJS web application into a number of websites. I'd like to be able to provide each website administrator with an HTML code, such as the following:
<div id='angular-integration-app'></div><script src="widget.js"></script>
With this HTML code inserted into the website, the website should load AngularJS and insert an AngularJS application as a child element of the element labeled with the ID of "angular-integration-app."
This Plunker has an implementation, however this implementation isn't working. It fails intermittently, with an error of:
Uncaught ReferenceError: angular is not defined application.js:1
Uncaught Error: [$injector:modulerr] angular.js:38
I've noticed that it usually works fine the first time it's loaded, but when the browser refresh button is pressed, it often fails. This is particularly true when it's not being hosted through Plunker.
Please advise on the best way to create a dynamic AngularJS application integration that works all the time.
This inconsistent behavior is because sometimes the page is cached and the code is executed synchonously, sometimes it does not.
To fix that, you need to wait for angular to be ready, then declare your module, and then bootstrap the document with your module. You cannot use ng-app in the HTML if the bootstrapping is executed "afterwards" (asynchronously, out of angular context). I have made the changes to show you how it should be:
var element = document.querySelector('#angular-integration-app');
angular.element(element).ready(function() {
var app = angular.module('myapp', []);
app.directive('customForm', function() {
return {
restrict: 'A',
template: 'hello world'
};
});
angular.bootstrap(element, ['myapp']);
});
http://plnkr.co/edit/7KbD1Okwx0MwhDIJXIGE?p=preview
Alternatively, if you don't want angular to mess up with your target html (and what happens if he is using another version of angularjs himself?), you could create an iFrame to isolate your angular, style, and code.
The code in this Plunker looks like it solves the problem. I'm now adding AngularJS as a child of the head element (the variable named "script"), and holding off on modifying the DIV or loading the AngularJS application until "script.onload." I incorporated some of the ideas from floribon's post into this Plunker as well.
script.onload = function() {
// code here
};

Lazy loading knockoutjs with bookmarklet failing

I'm attempting to fix a bookmarklet I wrote to track the URL changes in a single page application, specifically recording timesheet while using asana. It uses a script loader to embed jQuery and KnockoutJS libraries before init. I'm unable to find the ko object in global scope after the KnockoutJS library has initialized and cannot figure out why. To test, login to https://app.asana.com, open the Google Chrome developer tools' Console tab and try the following code:
var koScript=document.createElement('script');
koScript.type='text/javascript';
koScript.src='//ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js';
document.getElementsByTagName('head')[0].appendChild(koScript);
The Network tab shows the script downloading. The Elements tab shows the script as the last child of the head element. Yet ko remains undefined.
The short version is that:
Asana uses an internal module system that uses module.exports and require - the CommonJS standard you may know from node.js.
The knockout.js file checks the environment to determine if it should be setting window.ko or using module.exports or AMD-style define. If it detects CommonJS-style require it sets properties on exports instead of on a global ko object.
Workaround:
You could temporarily "copy" require off first:
_require = require; require = null
And then it should set window.ko as you're expecting!

How to load a script synchronously with RequireJS

I am using RequireJS in ASP.NET. There is a user control that includes a script file, and registers a startup script in order to initialize itself. Here's the generated code:
<script src="script/UserControls/myctrl.js" type="text/javascript"></script>
...
<script type="text/javascript">
function myCtrl1_init() {
// initialize control
// *JS ERROR* because myctrl.js hasn't run yet
Sys.Application.remove_load(myCtrl1_init);
}
Sys.Application.add_load(myCtrl1_init);
</script>
The myctrl.js file looks something like this:
require(['script/dep1', 'script/dep2'], function(dep1, dep2) {
MyCtrl = function () {
};
MyCtrl.init = function(id) {
dep1.doSomething();
}
};
So, the problem is that startup script runs before the myctrl.js file has had a chance to run. Currently, the require call uses a callback function, which obviously doesn't run until later, and this is the problem... the script returns and the browser continues to the startup script before MyCtrl has been created.
I have tried simply calling require(['script/dep1', 'script/dep2']); at the top of the file, but that doesn't block either, and the script fails because the dependencies haven't loaded yet. The dependencies are modules, by the way, e.g. they use define().
Is there a way to load a script file synchronously with RequireJS? The API documentation says that "Using RequireJS in a server-side JavaScript environment that has synchronous loading should be as easy as redefining require.load()", but I have no idea what this means.
Any suggestions?
I assume the script tag for require.js is above the contents you mention. If so, then I would convert myctrl.js to be a module (use "define('myctrl', ....)" instead of "require(.." inside it), then in the inline script tag content do something like:
<script type="text/javascript">
require(["myctrl"], function () {
function myCtrl1_init() {
// initialize control
// *JS ERROR* because myctrl.js hasn't run yet
Sys.Application.remove_load(myCtrl1_init);
}
Sys.Application.add_load(myCtrl1_init);
});
</script>
I am not familiar with ASP.NET, so I am not sure if it is OK to do those Sys.Application calls in a callback that may fire after DOMContentLoaded, but the above is the general idea.
There is no way to synchronously load a script in the browser with RequireJS, a callback method like above needs to be used. The require.load() information was for developers that want to make RequireJS adapters that run in sync environments (basically non-browser JS environments).

Categories

Resources