Very new to AngularJS, I am guessing the term for what I am trying to do is lazy load. I have looked at several different blogs and I have not found a complete working solution that is purely using AngularJS.
I understand that if I put the <script src="js/process1.js"></script> in index.html, all works fine, I am trying to cut down on the amount of js that is pulled down on the initial load.
With the script tag sitting in the partial, it is never loaded so the P1Ctrl is never created. So currently, if a user go into the application and never goes to process55, the user still has the code there for process55 even though it was never used.
Is there a way to load the file and inject the objects created in the process1.js into the app defined in main, at the time process1 route is executed?
index.html:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Large Angular App</title>
<link rel="stylesheet" href="lib/foundation/css/foundation.min.css" />
</head>
<body ng-app="largeApp" ng-controller="LargeAppController">
<div>
Home | Process1
</div>
<br/>
<br/>
<br/>
<ng-view>Test</ng-view>
<script type="text/javascript" src="lib/jquery/jquery.min.js"></script>
<script type="text/javascript" src="lib/angular/angular.js"></script>
<script type="text/javascript" src="lib/angular/angular-route.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
js/main.js:
var app = angular.module("largeApp", ['ngRoute']);
var appCtrl = app.controller("LargeAppController", function(){});
app.config(function ($routeProvider, $controllerProvider) {
// save references to the providers
app.registerCtrl = $controllerProvider.register,
$routeProvider.when('/', {templateUrl: 'partials/home.html'});
//Thinking I need to set up a resolve to fire off a script loader to load js.
$routeProvider.when('/process1', {templateUrl: 'partials/process1/process1.html'});
$routeProvider.otherwise({redirectTo: '/'});
});
partials/home.html:
<div>
Home Page
</div>
partials/process1.html:
<script type="text/javascript" src="js/process1/Process1Controller.js"></script>
Process 1 {{process1data}}
js/process1.js:
console.log("I made it here");
app.registerCtrl('Process1Controller',function($scope){
$scope.process1data = "Hello!";
}
]);
To implement lazy loading of controllers in simple way, you have to do the following:
Save $controllerProvider.register (which is the only method to add a controller into already bootstrapped AngularJS app) to variable in your app (main.js):
var app = angular.module('app',["ngRoute"]);
app.config(['$routeProvider', '$controllerProvider',
function($routeProvider, $controllerProvider) {
// remember mentioned function for later use
app.registerCtrl = $controllerProvider.register;
//your routes
$routeProvider.when('/', {templateUrl: 'partials/home.html'});
$routeProvider.when('/process1', {templateUrl: 'partials/process1.html'});
$routeProvider.otherwise({redirectTo: '/'});
}
]);
process1.html:
<script src="js/process1.js"></script>
<div ng-controller="P1Ctrl">
{{content}}
</div>
And now, in process1.js you use our registerCtrl:
app.registerCtrl('P1Ctrl', function($scope)
{
$scope.content = '...';
});
index.html probably remains the same. Check if your process1.js is being loaded (simply using console.log() right in the body of process1.js, not in P1Ctrl controller). If it isn't, include jQuery before Angular:
<script src="lib/jquery/jquery.js"></script>
<script src="lib/angular/angular.js"></script>
IMPORTANT: This method doesn't work with angular 1.2.0-rc.2 and 1.2.0-rc.3, because this little trick with jQuery doesn't work.
For more complex (and prettier) solution, with .js files as dependencies in route definitions, check that article: http://ify.io/lazy-loading-in-angularjs/ - it also works with rc.2 and rc.3. Here is plunk implementing described method: http://plnkr.co/edit/ukWikO5TVDtQ1l9WlrGD
Related
I've been trying to figure this out for a few hours now, and I can't seem to find the problem. I've read some other questions with similar problems, but they don't have any solutions that have worked for me.
I am having trouble registering my controllers. I am not able to register controllers outside of the file in which I declare the app. Originally, I set up the 'MainController' in a separate file, which failed. I was getting an error saying that "The controller with the name 'MainController' is not registered". Once I put MainController in the same file as the app is declared, there were no problems. However, when I have a lot of code, I don't want all the controllers in the same file, as it will become too difficult to read. Here are examples of my code:
angular.module('myApp', ['ngRoute']);
angular.module('myApp')
.controller('MainController', MainController);
I am keeping other controllers in different files, and they are not registering. For example, in home.controller.js:
angular.module('myApp')
.controller('HomeController', HomeController);
function HomeController(HomeService) {
}
This controller will not register, and I don't know why. Each HTML partial in ng-view has its own controller, and the ng-view is within the MainController. Here is the app.config.js file:
angular.module('myApp')
.config(function($routeProvider, $locationProvider) {
$routeProvider.when('/home', {
templateUrl: 'views/home.html',
controller: 'HomeController as home'
}).when('/profile', {
templateUrl: 'views/profile.html',
controller: 'ProfileController as profile'
});
$locationProvider.html5Mode(true);
});
Here is index.html:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8">
<title>My App</title>
<script src="vendors/angular.min.js"></script>
<script src="vendors/angular-route.min.js"></script>
<script src="scripts/app.module.js"></script>
<script src="scripts/app.config.js"></script>
<scripts src="scripts/home.controller.js"></scripts>
<scripts src="scripts/profile.controller.js"></scripts>
<script src="scripts/main.service.js"></script>
<script src="scripts/home.service.js"></script>
<script src="scripts/profile.service.js"></script>
<base href="/" />
</head>
<body ng-controller="MainController as main">
<header>
<h1>My App</h1>
</header>
<!-- Content varies -->
<div class="container">
<ng-view></ng-view>
</div>
</body>
</html>
I have successfully built projects like this in the past without problem, but I can't find any issue compared to those projects. Any help is appreciated!
When I've had this issue in the past, it was related to script loading order, especially with using async script loading. You don't appear to be doing that.
To troubleshoot:
Fire a console log statement inside the controller's function body (console.log('registering controller x')). This statement will either not show up, or will show up after the error.
Angular used to (and I presume it still does) try to wait for app to load and all controllers to register to app before running the code. Either Angular isn't waiting on this controller, or this controller isn't running.
From there, you would verify that the reference to the file is correct (put a console.log at the top of the file), or determine how Angular decides when it believes all controllers are loaded and why it doesn't wait on your controller.
I haven't dealt with Angular since 1.2, because I think it's a pretty bad framework. But that was my experience then, and it seems like the same basic architecture for this. Back then it was relying on Document.ready. I really hope they don't do that anymore (that's where I ran into my async script loader problems).
Best of luck.
My server using angular for routing. My server sending to the browser a HTML file that contains js file with routing (using angular js).
my server code (send to browser check.html contains the routing file main.js) :
var express = require("express");
var app = express(); // express.createServer();
app.use(express.static(__dirname + '/public'));
app.get("/*", function(request, response) {
response.sendFile(__dirname + '/public/check.html');
});
app.listen(8080);
check.html code:
<html data-ng-app="myApp">
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="angular.js"></script>
<script type="text/javascript" src="angular-route.js"></script>
<script type="text/javascript" src="main.js"></script>
</head>
<body>
</body>
</html>
after the browser gets the check.html file he doesnt redirect it to main.js in order to use the routing. I tried to debug it but the browser is stuck without doing nothing. my app is local and the url im trying to connect to is:
http://localhost:8080/stations
and all the files are loaded correctly without any errors on the console.
main.js code:
var myApp = angular.module('myApp', ['ngRoute']);
myApp.config(function($routeProvider) {
$routeProvider
.when('/',
{
controller: 'HomeController',
templateUrl: 'menu.html'
})
.when('/stations',
{
controller: 'StationsController',
templateUrl: 'check2.html'
})
.when('/',
{
controller: 'HomeController',
templateUrl: 'menu.html'
})
.otherwise({redirectTo: '/'});
});
myApp.controller('StationsController', function($scope){
$scope.check = {name:"ELAD!!"};
});
check2.html code:
<html>
<head>
</head>
<body>
<div>
<p>{{check.name}}</p>
</div>
</body>
</html>
Ok let's start fresh on angular..
Angular 101
You may know angular is essential for Single Page Application so what happens is you supply the first page that is check.html in your case but you should name it index.html it's a convention. khair.. what happens is when a route transition occurs in the your angular code that is something after # an it's purely client end or a soft redirection. so angular fires an AJAX request to retrieve the resource matching your templateUrl from router. then plugs it inside the <div ng-view></div> thus the redirection. notice the ng-view.
Well bellow is the proposed solution
the link should be http://localhost:8080/#stations as the angular matches handles the routes after #. Other routes like the link you provided are handed to the server.
your check.html should look like this.
<html data-ng-app="myApp">
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="angular.js"></script>
<script type="text/javascript" src="angular-route.js"></script>
<script type="text/javascript" src="main.js"></script>
</head>
<body>
<div ng-view></div>
</body>
</html>
and your check2.html should be in your public directory and have the code like
<div>
<p>{{check.name}}</p>
</div>
This question already has an answer here:
angular js ng-view returns blanc partials -- Express/ Jade
(1 answer)
Closed 7 years ago.
I am building an angular app following a tut. However, my angular ng-view is not rendering. I have seen a similar question here yet it has not been answered. Below is my dir structure
app.js
var app = angular.module('app', ['ngResource', 'ngRoute']);
angular.module('app').config(function($routeProvider, $locationProvider){
$locationProvider.html5Mode(true);
$routeProvider
.when('/', { templateUrl: 'partials/main', controller: 'mainCtrl'});
});
angular.module('app').controller('mainCtrl', function($scope){
$scope.myVar = "Hello Angular";
});
My layout.jade
doctype html
head
link(rel="styleSheet",href="css/bootstrap.css")
link(rel="styleSheet",href="vendor/toastr/toastr.css")
link(rel="styleSheet",href="css/site.css")
body(ng-app='app')
block main-content
include scripts
My main.jade
h1 This is a partial
h2 {{ myVar }}
The route in my server.js are set as
app.get('partials/:partialPath',function(req,res){
res.render('partials/' + req.params.partialPath);
});
app.get('*', function(req,res){
res.render('index');
});
my index.jade
extends ../includes/layout
block main-content
section.content
div(ng-view)
Although I am thinking that shouldn't be an issue because I am starting with a partial view which is part of a page. When I run my page it returns black. I inspected the elements and ensured that all the js and css where loaded. The html source below was generated on my page:
<!DOCTYPE html>
<head><link rel="styleSheet" href="css/bootstrap.css">
<link rel="styleSheet" href="vendor/toastr/toastr.css">
<link rel="styleSheet" href="css/site.css">
</head>
<body ng-app="app">
<section class="content">
<div ng-view></div></section>
<script type="text/javascript" src="vendor/jquery/dist/jquery.js"></script><script type="text/javascript" src="vendor/angular/angular.js"></script>
<script type="text/javascript" src="vendor/angular-resource/angular-resource.js"></script>
<script type="text/javascript" src="vendor/angular-route/angular-route.js"></script><script type="text/javascript" src="app/app.js"></script>
</body>
I was suspecting routeProvider from my app.js here
.when('/', { templateUrl: 'partials/main', controller: 'mainCtrl'});
tried
.when('/', { templateUrl: '/partials/main', controller: 'mainCtrl'});
All to no avail. Please where do I go wrong ? I have tried everything possible. I even restarted the tut yet still blank. Any help would be appreciated.
Thank you for your time. It turns out the issue is in my layout
doctype html
head
link(rel="styleSheet",href="css/bootstrap.css")
link(rel="styleSheet",href="vendor/toastr/toastr.css")
link(rel="styleSheet",href="css/site.css")
body(ng-app='app')
block main-content
include scripts
Changed to
doctype html
head
base(href='/')
link(rel="styleSheet",href="css/bootstrap.css")
link(rel="styleSheet",href="vendor/toastr/toastr.css")
link(rel="styleSheet",href="css/site.css")
body(ng-app='app')
block main-content
include scripts
What was missing is
base(href='/')
It does not load the templates if you remove that base. I learnt that from another tut video by tut plus "[Tuts Plus] Building a Web App From Scratch With AngularJS Video Tutorial" . The presenter specifically mentioned the important of the base(href='/') and warned never to forget . Alternatively , there is another good example from #Alex Choroshin answer here . you should download the doc he suggested . Its a perfect example. Thanks
I've just started using AngularJS for a new app I'm looking at putting together but I've run into a problem when using routes and views.
I've stripped this example down to the bare minimum but the issue remains. All this example is doing is hitting the server and returning the index.html page, which then sources Angular etc.
index.html
<!doctype html>
<html lang="en" ng-app="main">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" src="css/style.css" />
<script type="text/javascript" src="js/ext/angular.min.js"></script>
<script type="text/javascript" src="js/ext/angular-route.min.js"></script>
<script type="text/javascript" src="js/main.js"></script>
<script type="text/javascript" src="js/test.js"></script>
<base href="/ui/">
</head>
<body>
<div ng-view></div>
</body>
</html>
main.js
(function() {
var app = angular.module('main', ['ngRoute', 'test']);
app.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
.when('/test', {
templateUrl: 'html/test.html',
controller: 'TestCtrl'
})
.otherwise({
redirectTo: '/test'
});
$locationProvider.html5Mode(true);
}]);
})();
test.js
(function() {
var app = angular.module('test', []);
// get hierarchy
app.controller('TestCtrl', ['$scope', function($scope) {
alert('here');
}]);
})();
test.html
<div>FooBar!</div>
The alert gets fired infinitely but I just don't know why. I've seen other examples where ng-view and routing appear to be used exactly the same way, so I'm not sure what I'm doing wrong...
I had same problem sometime ago. Please, use firebug or some network control in the same browser at the developers tools panel where you can see the requests to the server for resources and then check that test.html file is requested and is correctly retrieved. It seems like the only one that is retrieved is the index.html and due this, the loop.
Probably you have to use this templateUrl value "/html/test.html" with "/" before. To localize this resource.
This is the idea that I'm proposing you. Localize the test.html resource with the correct way. I hope this can help you.
I had this issue today in March 2016. I have just found out what was causing the infinite loop when ng-view is present in the html (index.html in my case which is the initial html loaded at the start).
Ok, the problem was after all very simple one. I had this route provider setting in my app.js
angular.module('myapp',['ngRoute'])
.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl:'/index.html',
controller:'MyAppCtrl'
})
Since the initial html loaded is index.html, and the url at that point is '/', and the routeProvider invokes the code at when '/'. Yes, it loads index.html again, and again and again and again... till it dies. The solution is not to set index.html as the templateUrl for the '/' route. The html (template) should not include <div ng-view></div>.
Here's how I've done it, example here
Code
.config(['$routeProvider', '$locationProvider',function($routeProvider, $locationProvider) {
$routeProvider
.when('/test', {
template: '<div>test</div>',
controller: 'testCtrl'
})
.when('/other', {
template: '<div>Delete</div>',
controller: 'otherCtrl'
})
.otherwise({
redirectTo: '/test'
});
$locationProvider.html5Mode(true);
}]);
Ok, I solved my problem. I've accepted sergio's as it was closest to how I realised what the problem was - my app was requesting the html file from the application server, which is set up to return the index.html file as a default action. As the html request had no associated action, the default response of returning index.html was kicking in instead of the test.html file.
Once I changed the url so it was getting the html file from the web server, everything worked great. If I'd taken a moment earlier to actually think through what was happening, it would've been obvious.
Thanks for the responses!
I'm getting some variation of the following, for every single Angular module (animate, resource, route, touch etc):
Module 'ngResource' 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.
I'm relatively new to Angular. I read the docs on the error but I'm not sure how to apply them. Thoughts?
Here is the code where I declare the modules:
angular
.module('juddfeudApp', [
'ngAnimate',
'ngCookies',
'ngResource',
'ngRoute',
'ngSanitize',
'ngTouch'
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html'
})
.when('/about', {
templateUrl: 'views/about.html'
})
.when('/admin', {
templateUrl: 'views/admin.html',
controller: 'AdminCtrl'
})
.otherwise({
redirectTo: '/'
});
});
HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body ng-app="juddfeudApp">
<!-- all angular resources are concatenated by Gulp in lib.js-->
<script src="build/lib/lib.js" type="text/javascript"></script>
<script src="build/main.js" type="text/javascript"></script>
</body>
</html>
You need to reference them in your html file.
So add <script src="filename.js"></script> for each module/file you want to load.
did you add this <script src="angular-resource.js"> ?
When you get an error like this, it's likely that you aren't successfully loading the Angular module scripts in your HTML file.
Some answers here suggest making sure you've referenced the scripts somewhere in your HTML file.
That is, if you're trying to add multiple Angular modules, you should have several scripts being loaded before your own JS, like this:
<script src="../bower_components/angular/angular.js"></script>
<script src="../bower_components/angular-resource/angular-resource.js"></script>
<script src="../bower_components/angular-cookies/angular-cookies.js"></script>
<script src="../bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="../bower_components/angular-animate/angular-animate.js"></script>
<script src="../bower_components/angular-touch/angular-touch.js"></script>
<script src="../bower_components/angular-route/angular-route.js"></script>
<script src="myMainJsFile.js"></script>
That may fix the problem.
You might also consider checking to make sure your scripts actually exist in the place you are referencing them -- for me, bower had not properly installed them all on the first time around, so they weren't being picked up by gulp-concat -- or ensuring that your task-runner of choice (Gulp/Grunt) is configured properly.