I've just started to learn about RequireJs but am unable to load a js dependency using it's custom shortened name. I don't understand what I'm doing wrong here, I try to load the knockout js library using only "knockout" but it throws an error
Error: Script error for "knockout"
http://requirejs.org/docs/errors.html#scripterror
if I use "knockout-3.4.0" it works fine but I'd prefer to use the shortened
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" data-main="js/init.js" src="js/require.js"></script>
</head>
<body>
<h1 data-bind="text: TabIndx">Hello World</h1>
<script>
require(['knockout', 'viewModel'], function(ko, viewModel) {
var vm = new viewModel();
ko.applyBindings(vm);
});
</script>
</body>
</html>
require.config({
baseUrl: 'js',
paths: {
knockout: 'knockout-3.4.0',
viewModel: 'viewModel'
}
});
I suspect this is because RequireJS hasn't fully loaded itself and its custom configuration before you're requesting local paths. What you should really be doing if you're using RequireJS is having a module responsible for creating the view model and applying the bindings like in your example.
// app.js
define(['knockout', 'viewModel'], function (ko, viewModel) {
var vm = new viewModel();
ko.applyBindings(vm);
});
require.config({
baseUrl: './js/',
paths: {
knockout: 'knockout-3.4.0',
viewModel: 'viewModel',
app: 'app'
}
});
I'm not sure how init.js looks, but here I have made it a little module responsible for launching the app.js file.
define(['app'], function (app) {
app.init();
});
Your config should ideally be refactored into its own file, where require-config.js just contains your config snippet, like so: -
<script type="text/javascript" data-main="js/init.js" src="js/require.js"></script>
<script type="text/javascript" src="js/require-config.js"></script>
Related
I have an existing angular web app which doesn't use require.js. I have to create a new business module in the existing application. Can I use require.js for the new module only? So that I don't have to touch the existing code?
The existing index.html looks like this:
<html>
<head>
...
</head>
<body>
...
<script src="http://cdn.gse.site/angular/1.2.9/angular.js"></script>
<script src="js/angular-ui-router.js"></script>
<script src="js/services/angDashboardService.js"></script>
<script src="js/controllers/angDashboardController.js"></script>
<--- More custom scripts here --->
</body>
</html>
I tried including require-main.js in the existing index.html file without removing any of the existing script tags.
The require-main.js looks like this :
require.config({
baseUrl: 'js',
paths:{
'angular' : '...'
},
shim: {
'angular': {export: 'angular' },
'new-module': {
deps: ['angular'], export: 'new-module'
}
}
});
require(['new-module'], function(){});
I am getting the error as following:
Uncaught Error: [ng:btstrpd] App Already Bootstrapped with this Element '<body class="preload ng-scope" ng-app="angDashboard">'
Can we use requirejs in an angular application to manage/modularize only a part of the application?
Yes you can (but why...?). You will be hits by some serious headache if you are not ware of what are you doing
Anyways to able to do this you must be fully understand the concept of angularJS and requireJS .
<script src="http://cdn.gse.site/angular/1.2.9/angular.js"></script>
<script src="js/angular-ui-router.js"></script>
<script src="js/services/angDashboardService.js"></script>
<script src="js/controllers/angDashboardController.js"></script>
This mean you already had an angular app running. So you will not (should not) config or load angular anymore with requireJS
require.config({
baseUrl: 'js',
paths:{
'async-module' : '...'
},
// You won't use 'shim' with this structure
// shim: {}
});
async-module.js
// assuming somewhere you have did this
// var app = angular.module([...]);
//
// NOW you need to convert this 'app' to global variable. So you can use it it requirejs/define blocks
// window.app = angular.module([...]);
define(function(){
window.app.controller('asyncCtrl', function($scope){
// controller code goes here
});
});
Then somewhere inside your app, when you want to load this async-module
requirejs(['async-module'], function(){
console.log('asyncCtrl is loaded!');
});
SUMARY >>
It is possible to do what you asked but it does not very effective. And will be like hell in code management.
If this answer took you lesser than 5 mins to understand, you can give it a try.
If it took you longer than 5 mins to understand. I am highly not recommending you to do this. Using requireJS with angularJS in common way (everything loaded by requireJS) is already complicated and tricky. And this use case even beyond that.
I am trying to lazy load files by reading this POST.
But not able to implement it. I am getting a 'module error' Error in the firebug.
Here is my project structure:
root
|----app
|----script.js
|----app.js
|----appBootstrap.js
|----login
|----login.html
|----login.js
|----vendor
|----angular.min.js
|----angular-route.min.js
|----index.html
index.html code:
<!DOCTYPE HTML>
<html ng-app="myApp">
<head>
</head>
<body ng-view="">
<!-- javascript files-->
<script type="text/javascript" rel="javascript" src="app/vendor/angular.min.js"></script>
<script type="text/javascript" rel="javascript" src="app/vendor/angular-route.min.js"></script>
<script type="text/javascript" rel="javascript" src="app/script.js"></script>
<script type="text/javascript" rel="javascript" src="app/appBootstrap.js"></script>
</body>
</html>
app.js code :
(function()
{
var myApp = angular.module('myApp',[]);
myApp.config(function($routeProvider, $controllerProvider, $filterProvider, $provide)
{
myApp.controllerProvider = $controllerProvider;
myApp.compileProvider = $compileProvider;
myApp.routeProvider = $routeProvider;
myApp.filterProvider = $filterProvider;
myApp.provide = $provide;
$routeProvider.when('/', {templateUrl:'login/login.html', resolve:{ deps: function($q, $rootScope)
{
var deferred = $q.defer();
// Add dependencies here
var dependencies =
[
'login/login.js'
];
$script(dependencies, function()
{
// all dependencies have now been loaded by $script.js so resolve the promise
$rootScope.$apply(function()
{
deferred.resolve();
});
});
return deferred.promise;
}}});
});
})();
appBootstrap.js code:
$script(['app.js'], function()
{
angular.bootstrap(document, ['myApp'])
});
When I try to load the root folder in the browser, I get the following error
Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.2.13/$injector/modulerr?p0=myApp&p1=Error%3A%…calsearch_new%2Fbranches%2Fb1.0%2Fapp%2Fvendor%2Fangular.min.js%3A32%3A232)
Could someone please explain what am I doing wrong?
Update 1: As suggested by #kartikluke added the ngRoute file (angular-route.min.js) but still showing same error but twice now
Well I followed the link in the error
Module Error
error
Description
This error occurs when a module fails to load due to some exception. The error message above should provide additional context.
In AngularJS 1.2.0 and later, ngRoute has been moved to its own module. If you are getting this error after upgrading to 1.2.x, be sure that you've installed ngRoute.
Add ngRoute
Alright so it doesn't seem to be ngRoute.
If you are not sure which module is missing, use the not minified angular.js which gives a readable error message: "Error: [$injector:nomod] Module 'ngRoute' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument."
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.js"></script>
<script type="text/javascript" rel="javascript" src="app/vendor/angular-route.js"></script>
<script type="text/javascript" rel="javascript" src="app/app.js"></script>
<script type="text/javascript" rel="javascript" src="app/script.js"></script>
<script type="text/javascript" rel="javascript" src="app/appBootstrap.js"></script>`
Alright I looked through your code and I found that after replacing with the unminified code and adding app.js to the scripts I found that the module $compileProvider was not injected.
myApp.config(function($routeProvider, $controllerProvider, $filterProvider, $provide, $compileProvider)
Pretty simple in the end. Use the cdn and the unminified code will give you the correct errors.
Is possible to have requirejs config at one place and reuse it in modules?
such as
main.js:
requirejs.config({
baseUrl: "static/js",
paths: {
"jquery": "http://code.jquery.com/jquery-1.9.1.js",
"jquery-ui": "http://code.jquery.com/ui/1.10.2/jquery-ui.js"
},
shim: {
"jquery-ui": {
deps: ["jquery"]
}
}
});
and
public.js:
define(["main", "jquery", function(main, $) {
// do some public stuff
});
client.js:
define(["main", "jquery", function(main, $) {
// do some client stuff
});
And on my public part of web have
<script type="..." src="js/require.js" data-main="js/public.js"></script>
And on client part of web
<script type="..." src="js/require.js" data-main="js/client.js"></script>
And also I would like to have a module for each page. So for example to have a index module on public
<script ...>
require('public/index');
</script>
and
public/index.js:
define(["jquery", "slideshow"], function($, s) {
$( function() { s.init() } );
});
Is that possible with RequireJS?
Thank you for answers.
data-main is a useful shortcut in the very simple case but I don't find it terribly useful beyond that, the solution is to dump it entirely.
Load your main explicitly on each page, then use the callback to load your view-specific scripts.
So you have in public.html:
<script src="/Scripts/require.js"></script>
<script>
require('main', function(){
require('public');
})
</script>
and in client.html:
<script src="/Scripts/require.js"></script>
<script>
require('main', function(){
require('client');
})
</script>
I've written a blog post expounding on this idea here.
I edit my answer as you make the question clearer.
In any page you include require.js, you should also include main.js to define your RequireJS config.
You can't do things like
define(["main", "jquery", function(main, $) {
// do some public stuff
});
because ReuiqreJS load dependencies asynchronously. Although "main" is placed before "jquery", it's not guaranteed RequireJS will load them in that sequence.
So your public/index.html can be like:
<script type="..." src="js/require.js"></script>
<script type="..." src="js/main.js"></script>
<script ...>
require('public/index');
</script>
Can I use Require.js in development without using the data-main attribute to load in my initial script? ie. <script data-main="scripts/main" src="scripts/require.js"></script> I'm finding it difficult for me to work with this attribute in my development environment.
Yep, take a look at the documentation: http://requirejs.org/docs/api.html#config
You need to call require.config() and set baseUrl. Based on your example:
<script src="scripts/require.js"></script>
<script>
require.config({
baseUrl: "scripts"
});
require( [ /*...*/ ], function( /*...*/ ) {
/*...*/
});
</script>
http://requirejs.org/
I recently downloaded require.js 2.0 and I am getting error in my console:
Uncaught TypeError: Object function (){var g=ga.call(arguments,0),e;if(f&&v(e=g[g.length-1]))e.__requireJsBuild=!0;g.push(d);return b.apply(null,g)} has no method 'nameToUrl'
Is order.js plugin still supported by requirejs? I don't see its documentation in the website.
When I try to remove the file the script breaks.
In my index file, I included requirejs script in the head section:
<!DOCTYPE html>
<html>
<head>
<title>
My Mobile Application
</title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" />
<link rel="stylesheet" href="public/css/style.css" />
<script data-main="scripts/main.js" src="scripts/require.js"></script>
</head>
<body></body>
</html>
Then in my main.js file:
requirejs.config({
//By default load any module IDs from js/lib
baseUrl: 'js/lib',
//except, if the module ID starts with "app",
//load it from the js/app directory. paths
//config is relative to the baseUrl, and
//never includes a ".js" extension since
//the paths config could be for a directory.
paths: {
app: '../app',
assets: '../assets',
views: '../app/views',
templates: '../app/templates',
collections: '../app/collections',
models: '../app/models'
}
});
// Start the main app logic.
requirejs([
'jquery/jquery',
'assets/jqm.config',
'jquery/mobile',
'text'
]);
require([
'app'
],
function( App ){
$(document).ready( function(){
App.initialize();
});
}
);
I sees to it that App.initialize doesn't have any errors and what App.initialize is doing is just simple geo location. The requirejs simply ask for order.js, and when I put the code it's having the same error as mentioned above.
Thank you!
Your assumption that order is no longer supported is correct. It was removed in favour of the shim configuration option:
So, the the order plugin has been removed and following the lead of
Tim Branyen and Dave Geddes, of use and wrap respectively, requirejs
2.0 integrates that kind of dependency tree specification directly in requirejs.
Require 2.0 upgrade notes - https://github.com/jrburke/requirejs/wiki/Upgrading-to-RequireJS-2.0
Also, check the shim documentation on the RequireJS site - http://requirejs.org/docs/api.html#config-shim
Oh figured it out.
//This is our main applicatoon boot loader or bootstrap
//here we are loading necessary scripts dependencies like
//jquery, jqm.config, mobile, text
requirejs.config({
baseUrl: 'js/libs',
//except, if the module ID starts with "app",
//load it from the js/app directory. paths
//config is relative to the baseUrl, and
//never includes a ".js" extension since
//the paths config could be for a directory.
paths: {
app: '../app',
assets: '../assets',
views: '../app/views',
templates: '../app/templates',
collections: '../app/collections',
models: '../app/models'
}
});
// Start the main app logic.
require(["jquery","assets/jqm.config","jquery/mobile","text","app"],
function(
$,
config,
mobile,
text,
App
) {
//the jquery.alpha.js and jquery.beta.js plugins have been loaded.
$(function() {
App.initialize();
});
});