I'm fairly new to Angular JS.
I was doing some practice demos with require JS along with angular routing using route provider in a well defined folder structure.
I tried searching for similar angular router problems but most do not have any folder structure, Their code was present in script tags.
I hope somebody has the patience to have a quick look and checkout why the route provider seems so non functional despite everything seeming to be done correct. :)
Anyway,
I have an index.html that simply loads the require JS with a source
Index.html
<!DOCTYPE html>
<html>
<head>
<title>MyApp</title>
<meta charset="utf-8"/>
<script data-main="assets/require/requireConfig" src="assets/vendor/require.js"></script>
<link rel="stylesheet" href="assets/css/site.css">
</head>
<body>
<ng-view></ng-view>
</body>
</html>
The Require JS source looks as follows where 'router' is the standard angular-router.
'myApp' would be the app I'm going to bootstrap.
The data source of Require JS
requirejs.config({
baseUrl: 'assets',
paths: {
'myApp': 'require/myApp',
'angular': 'vendor/angular',
'router': 'vendor/angular-route',
'domReady': 'vendor/dom-ready'
},
//Shim is also used to specify if one module must be loaded only after another
//angular does not support AMD out of the box, put it in a shim
shim: {
'angular': {
exports: 'angular'
},
'router': {
deps: ['angular'],
exports: 'router'
}
},
// kick start application
// The ./ represents the base URL given at the top
deps: ['./require/startup']
});
So Now I'm going to run the startup.js to bootstrap my app file
The following is how my startup.js looks
Angular Bootstrapping
define([
'require',
'angular',
'myApp'
], function (require, angular) {
'use strict';
require(['domReady!'], function (document) {
angular.bootstrap(document, ['myApp']);
});
});
And finally....
The Route Provider that is causing all the problems is defined in myApp.js
define(['angular','router'], function (angular) {
'use strict';
var myApp = angular.module('myApp', ["ngRoute"]);
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/login', {
templateUrl: '../../modules/login/login.html'
});
$routeProvider.when('/home', {
templateUrl: '../../modules/home/homepage.html'
});
}]);
});
Ok, So I run the application on an nginx server.
http://localhost/login
OR
http://localhost/home
does not direct me to the required pages I have specified in the templates.
However
If I specify a "$routeProvider.otherwise" it always redirects to it.
If I change $routeProvider.when("/login") to
$routeProvider.when("/"), The router opens up the login page but
complains there is no controller associated with the view specified.
(Hence my conclusion that the template URLs were pointing correctly)
Deciding to create a controller 'loginController' throws the error that the 'controller is not registered'. For which when I digged around that is due to bootstrapping. (Wha?. So whats good about requireJS? But I'll leave that question for another time)
So, why such weird behavior by the route provider?
I do not see it?
Related
EDIT As far as I understood through further research AngularJS isn't capable of injecting that controller code the way I wanted it to do. Anyway, I'm still interested in why exactly doesn't it work and how should it be done.
I've been trying to create my own AngularJS + RequireJS project seed and I've run into issues with app modules loading (I see them in the network inspector) but never actually executing.
So I've stripped down the app to just the AngularJS library with basic dependencies handled through in RequireJS and I've noticed that the app loads all of the files and modules properly but the top level application module controller (and now the only module in the app itself) that I'm bootstrapping onto the document never executes. Using ng-inspector I've come to a conclusion that there's also no controller scope defined.
There are no errors whatsoever in the console and what I can confirm is that app bootstraps properly and loads all of the modules but the appController is never executed.
Here's the code of the appBootstrap.js:
//requirejs config
require.config({
baseUrl: '/',
paths: {
'lib' : 'scripts/lib/',
'angular' : 'vendor/angular/angular.min'
},
shim: {
'angular': {
exports: 'angular'
}
}
});
//the actual app bootstrapping
require(['lib/appVendorLibs'], function(){
require([
'lib/appModule'
], function(appModule) {
angular.bootstrap(document, [appModule.name]);
});
});
Here's the appVendorLibs.js:
define([
'angular'
], function() {});
And here's the barebones appModule.js that I've come up with in order to test the controller execution that fails:
define([
'angular',
'lib/appController'
], function(angular, appController) {
var app = angular.module('app', []);
app.controller('appController', appController);
return app;
});
Here's the appController.js:
define([], function() {
var appController = function($scope, $rootScope){
$rootScope.aTestVar = "OK";
$scope.testObject = {};
$scope.testObject.text = "OK";
console.log("OK");
};
return ['$scope', '$rootScope', appController];
});
That console.log() call is never occurs nor do those lines referencing the $rootScope and $scope do anything.
Also, I've got ng-bind in my index.html that should be displaying the testObject.text variable but that never happens.
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="/styles/styles.css"/>
<title>AngularJS Module Loading Seed</title>
<base href="/">
</head>
<body>
<!-- Main Content Container -->
<p ng-bind="testObject.text"></p>
<script src="/vendor/requirejs/require.js" data-main="/scripts/lib/appBootstrap.js"></script>
</body>
</html>
What could be the problem here?
I am using the grunt task grunt-angular-templates for precompiling angular templates in my app, which has resulted in output like that:
$templateCache.put('src/ng-app/views/story/page.html',
//...html
but this route is throwing a 404 on the template file
.when('/:pageId.aspx', {
templateUrl: 'src/ng-app/views/story/page.html',
I've seen another post about setting the ID of the template and specifying that in the route but I don't know how to do that for external files - the example uses inline templates like that:
<script type="text/ng-template" id="login.html">
login.html
</script>
Simple solution in the end - I had to ensure the view script generated by ngTemplates was included before route declarations (i have those in a separate script routes.js)
Its also key to ensure the module is the same in ngTemplates grunt:
var app = angular.module('MyApp.Web'...
ngtemplates: {
app: {
src: 'src/ng-app/views/**/*.html',
dest: 'dist/src/js/ng-views.js',
options: {
module: 'MyApp.Web'
}
}
}
Adding templates as a dependency made no discernible difference (as I found on another post):
angular.module('templates', []);
var app = angular.module('MyApp.Web', [
'ngRoute',
'youtube-embed',
'templates'
]);
I'm getting this error when using the recommended component loading method (See step 3 )
Error: Module name "angular-ui-router" has not been loaded yet for context: _. Use require([])
app module definition:
<script>
var adminApp = angular.module('adminClientApp', [require('angular-ui-router'), 'ngMaterial', 'ngResource', 'ngMessages', 'ngMdIcons']);
</script>
According to the doco, there isn't a need to include a script tag - it will be loaded via requirejs
Requirejs main.js definition:
require.config({
paths:{
'angular-ui-router': 'vendor/angular-ui-router/release/'
},
shim:{
'angular': {
exports: 'angular'
}
}
});
app layout:
-- root
index.html
main.js
-- js
-- app (angular files here)
app.js
-- vendor (3rd party libs)
requirejs main.js setting in index.html
<script data-main="main.js" src="vendor/requirejs/require.js"></script>
The guide you are using is not made for RequireJS. After applying the instructions there, you are doing something like this:
<script>
var myApp = angular.module('myApp', [require('angular-ui-router')]);
</script>
This will generally fail to work with RequireJS because calling require with a single string fails unless the module is already loaded. This call is guaranteed to work only if it is inside a define, like this:
define(function (require) {
var myApp = angular.module('myApp', [require('angular-ui-router')]);
});
This code is a module which should be in a separate .js file and loaded with require(['module name']). (Note that the parameter is an array of strings. This is a different form of require than the one that takes a single string parameter.)
You should use Component, which is what the author of the guide you are using was using when he/she wrote the guide, or a tool that is equivalent to it. Otherwise, you need to convert your code to work with RequireJS.
How would it be possible to register new Angular modules in Zeppelin:
Based on this Angular example
https://material.angularjs.org/latest/getting-started
Here is the possible converted code in Zeppelin (the same code works fine in a standard webapp)
print(s"""%angular
<div id="myAngularApp">
<md-button class="md-raised md-primary">Angular Material Button</md-button>
</div>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.1.0-rc2/angular-material.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.js"></script>
<script>
require.config({
paths: {
'angular': 'http://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min',
'ngAnimate': 'http://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-animate.min',
'ngAria': 'http://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-aria.min',
'ngMaterial': 'http://ajax.googleapis.com/ajax/libs/angular_material/1.1.0-rc2/angular-material.min'
},
shim: {
'ngAnimate': ['angular'],
'ngAria': ['angular'],
'ngMaterial': {
deps: ['ngAnimate', 'ngAria']
}
}
});
require([ 'angular', 'ngMaterial' ], function () {
var app = angular.module('StarterApp', ['ngMaterial']);
angular.bootstrap(document.getElementById('myAngularApp'), ['StarterApp']);
return app;
});
</script>
""")
Unfortunately, I didn't find any ways to make it work. I tried with multiple ways, nothing works!
In brief, how to register a new Angular Module within Zeppelin?
The Angular Display system looks nice but is useless if no external modules can easily be registered.
Please, help :) Or provide a concrete example
According to an excellent explanation of how to add translation using angular-translate (https://technpol.wordpress.com/2013/11/02/adding-translation-using-angular-translate-to-an-angularjs-app/)
I have a breaking my head error and I'm wondering why that happens? And what am I doing wrong?
Error:
angular.js:36 Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.2.26/$injector/modulerr?p0=app&p1=Error%3A%20…alhost%3A9085%2FScripts%2Fcomponents%2Fangular%2Fangular.min.js%3A18%3A170)
Aim:
Partial loading translations in my entire app
What I've done:
Downloaded (both) via bower and included into the project.
angular-translate
angular-translate-loader-partial
Added them into ReguireJS config file (after Angular)
'angular': '../Scripts/components/angular/angular.min',
'ngAnimate': '../Scripts/components/angular-animate/angular-animate.min',
'ngResource': '../Scripts/components/angular-resource/angular-resource.min',
'ngRoute': '../Scripts/components/angular-route/angular-route.min',
'ngCookies': '../Scripts/components/angular-cookies/angular-cookies.min',
'pascalprecht.translate': '../Scripts/components/angular-translate/angular-translate.min',
'angularTranslate': '../Scripts/components/angular-translate-loader-partial/angular-translate-loader-partial.min'
Added shim:
'pascalprecht.translate': {
deps: ['angular']
},
'angularTranslate': {
deps: ['pascalprecht.translate']
}
In app.js file included dependencies (at the end, after angular stuff):
'pascalprecht.translate',
'angularTranslate',
var app = angular.module('app', ['...',
'pascalprecht.translate',
'angularTranslate' ]);
App.js config
app.config(['$routeProvider', '$locationProvider', '$httpProvider', '$translateProvider', '$translatePartialLoaderProvider',
function ($routeProvider, $locationProvider, $httpProvider, $translateProvider, $translatePartialLoaderProvider) {
Stuff in controllers config:
define(
[
'angular',
'./services/services',
'./controllers/controllers',
'./directives/directives',
'./filters/filters',
'pascalprecht.translate'
],
function(angular) {
'use strict';
var module = angular.module('common', ['common.services', 'common.controllers', 'common.directives', 'common.filters', 'pascalprecht.translate']);
return module;
});
Controller
define(function (require) {
'use strict';
function angularTranslate ($translateProvider, $translatePartialLoaderProvider) {
$translateProvider.useLoader('$translatePartialLoader', {
urlTemplate: '../Translations/locale-{part}.json'
});
$translateProvider.preferredLanguage('en');
}
return angularTranslate;
});
After precisely following above tutorial I still get thi error.
I albo searched in github and stackoverflow but nothing works for me.
Please help!
Short: You dependency management in RequireJS is not correct. The controller's module should require angularTranslate, not pascalprecht.translate.
Long:
At first I would advice you using the official documentation and guide which you will found at https://angular-translate.github.io/
I also recommend using both the latest AngularJS (which is 1.5.x atm) and angular-translate (which is 2.10.x atm).
Additionally, I would also advice using only the non minified versions of libraries because they will give you a much better experience. Minified source files are not for the developer.
And I would also appreciate working demo using JSFiddle, Plnkr or others because they give everyone a running proof of concept/bug.
Said this, it is not clear which version of angular-translate you are using. If you have run bower install angular-translate, you will probably have the latest already -- but the page behind the link you have referenced is made with an older one (about three years old). APIs have changed.
Coming to you actual issue: I would say you have mixed the problems both in AngularJS and RequireJS which leads in such exceptions.
First of all: Your (shim) configuration for RequireJS is misleading/confusing. You should not name the partial loader plugin as angularTranslate.
'angularTranslate': '../Scripts/components/angular-translate-loader-partial/angular-translate-loader-partial.min'
and
'angularTranslate': {
deps: ['pascalprecht.translate']
}
Less confusing would be a name like pascalprecht.translate.partialLoader.
And now the RequireJS module dependency management:
You have defined a shim dependency angularTranslate -> pascalprecht.translate. Whenever the last one will be requested, the first one will be loaded before. That's fine.
You have defined your app depends on both pascalprecht.translate and angularTranslate (which is the partial loader actually). This is fine, but the first one is actually obsolete. It will be available automatically because you have defined the shim dependency already.
However the controller's module only requires the core library pascalprecht.translate.
This means: The dependency management resolver of RequireJS will not wait for the partial loader (no reason it should do this) and therefor it can/will be not available when processing the AJS injections (here: translatePartialLoaderProvider).
Disclaimer: I'm the co-maintainer of the AngularJS plugin angular-translate.
app.js looked like this:
define(
[
...
'pascalprecht.translate',
'angularTranslate',
],
var app = angular.module('app', ['...',
'pascalprecht.translate',
'angularTranslate' ]);
but it should be like:
define(
[
...
'pascalprecht.translate',
'angularTranslate',
],
var app = angular.module('app', ['...',
'pascalprecht.translate' ]);
I've defined submodule angular-translate-loader-partial as normal module and that causes the error. Dependency between both modules (angular-translate and angular-translate-loader-partial) should be made only in requirejs shim.