Angular - scripts load order - javascript

I've just started with Angular after many years working with MVC. I'm quite familiar with js, HMTL but still beginner in the Angular world.
I lost 3 hours trying to figure out what is wrong with my app.
So the app has 3 files
index.html
<body ng-app="perica">
<p>main</p>
{{ tagline }}
<a ng-click="logOut();">Logout</a>
<div ng-view><p>inside</p></div>
</body>
<script type="text/javascript" src="../components/angular/angular.js"></script>
<script type="text/javascript" src="../AgularApp.js"></script>
<script type="text/javascript" src="../controllers/AcountController.js">
AngularApp.js
debugger;
angular.module('perica', ['ngRoute']).config(['$routeProvider','$locationProvider', function ($routeProvider, $locationProvider) {
console.log('in');
debugger;
$routeProvider.when('/test', {
templateUrl: 'views/Account/_Login.html'
})
$locationProvider.html5Mode(true);
}]);
and AccountController.js
var myApp = angular.module('perica', []);
myApp.controller('AcountController', ['$scope', function ($scope) {
$scope.tagline = 'The square root of life is pi!';
}]);
So as you can see it is a super simple application.
By all the coding logic, I should load angular core scripts the first, then my angular app and at the end angularcontroles.
When I run the app, Chrome hit the first debugger (above angular.module inside AngularApp.js file) and jumped straight into AccountContoler.js and completely ignored what is defined inside of the AngularApp.js.
but
When I reversed paths and put first AccountController.js and afterwards AngularApp.js everything worked without any issue
I would be really grateful if someone can shed some light on this issue
Thanks!

By using...
var myApp = angular.module('perica', [])
... in your AccountController.js, you're not loading your already existing 'perica' application (declared in the previously loaded AngularApp.js):
you are re-defining the perica application.
The correct way to refer to your already existing module is using:
angular.module('perica')
^
no dependency declared
instead of:
angular.module('perica', [])
^
dependencies
The logic behind this is quite simple once you're acquainted to it: if you're declaring dependencies while "loading" a module, you're creating that module. Otherwise, you're referring to it.
TL;DR: You're basically using a setter here twice and never actually enhancing your existing module.
Here's a working JSFiddle (link) with your application running. I loaded AngularJS directly from the Javascript framework/extensions menu and referred to an external JS resource for angular-route (fetched from cdnjs: https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular-route.min.js).
I basically simply concatenated both your AngularApp.js and AccountController.js contents to emulate loading them one after the other.
Please note that your also have to declare the controller that controls your view: I took the liberty to enhance your <body ng-app="perica"> element as follows:
<body ng-app="perica" ng-controller="AcountController">

Related

Should i include all the script tags for all the controllers in index.html? [duplicate]

This question already has answers here:
Angularjs add controller dynamically
(3 answers)
Closed 3 years ago.
I'm creating a SPA with angularjs and have a separate folder for each feature in the administration panel that contains the partial view and the controller like so:
files and folders structure
The problem i'm facing now is i find my self having to add a script tag which references all the .JS files of all the controllers.
<script src="assets/js/angular.min.js"></script>
<script src="app.js"></script>
<script src="views/clients/clients_controller.js"></script>
<script src="views/clients/orders_controller.js"></script>
This means that if the user is viewing the client data, the whole scripts for the orders, the products, etc..... will be loaded.
Now if I reached a point where i have about 100 or so controllers in my app it will be a huge amount of JS scripts loaded for no reason at all.
I'm sorry I've been programming for about 17 years, started with php to python and I've used angularjs before as a part of ionic framework app but never as a web application
also it's my first time ever I ask a question on stack overflow so please bear with me and thanks in advance.
For this problem we can use oclazyload:
var app = angular.module("app", ["ui.router","oc.lazyLoad"]);
In this example we have ui-router to changes route and with each route we load state files as controller or service
$stateProvider.state("main", {
url: "/",
templateUrl: "view.html",
controller: "mainController",
resolve: {
loadMyCtrl: ["$ocLazyLoad", function ($ocLazyLoad) {
return $ocLazyLoad.load({
files: ["mainController.js"] //["mainController.js", "mainService.js"]
});
}]
}
});
Here is how you can lazy load controllers without using any library.
First get a reference of your control provider where you bootstrap the app. You can attach this to your app object itself.
var myApp = angular.module('myapp', [])
.config(['$controllerProvider', function($controllerProvider) {
myApp.controlProvider = $controllerProvider;
}]);
Now put your controller in to .js or inside a script in an html file you want to add to the DOM - or, maybe in a route.
myApp.controlProvider.register('my-lazy-controller', ['$scope', function($scope) {
}])
If you don't want to use this in a route, load this new script or html using an appropriate method. You can use jQuery .load() if your have the controller in an html file or jQuery getScript() for loading .js file

How to put controller in another file in Angular 1.2?

I'm trying to separate the controller file from the module file (in app.js). But executing this in browser gives me an error. It works only if I put controller and module code in one file. But doesn't work if I put contoller in another file.
Here's my code for module (app.js):
var CoursePlannerApp = angular.module("CoursePlannerApp", []);
And for the controller (CoursePlannerAppCtrl.js file):
CoursePlannerApp.controller("coursePlannerCtrl", function ($scope) {
});
Can anybody explain me please, why it doesn`t work? Thanks.
In your app file
angular.module('app',[]); // initialise application
In your controller file
angular.module('app').controller('myCtrl', [function(){}]); //create controller
And make sure you loaded both files into the browser - app and than controller
If you are not working with some kind of bundler (like webpack), you put all of your files on the global scope, therefore, you should manage the order of loading the files.
At your case, you should put app.js to load before CoursePlannerAppCtrl.js. In that way, app.js will put CoursePlannerApp on the window, and you will have an access to it from CoursePlannerAppCtrl.js.
<script src="angular.js"></script>
<script src="app.js"></script>
<script src="CoursePlannerAppCtrl.js"></script>
You need to include the script tags in correct order. Just like below
<script src="../lib/angular.js"></script>
<script src="CoursePlannerApp.js"></script>
<script src="coursePlannerCtrl.js"></script>

Angular JS Injecting Custom Service

I can't get angular to accept my custom service, which is in a seperate file. I know this is all over stack overflow, but I just can't tell where I'm messing up.
Html:
<!DOCTYPE html>
<html lang="en" ng-app="angularApp">
<head>
<!-- ANGULAR -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular-sanitize.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-route.js"></script>
<link href="styles/angularApp.css" rel="stylesheet">
<script src="scripts/controllers/angularApp.js"></script>
<script src ="scripts/services/clearCodemirror.js"></script>
Main angular javascript file (contains my controller)
var myApp = angular.module("angularApp", ["ui.codemirror","ui.bootstrap", "ngSanitize", "ngRoute"]);
myApp.controller("mainController", ["$scope", "$timeout", "clearCodemirror", function($scope, $timeout, clearCodemirror){
Service I'm trying to inject:
var myApp = angular.module("angularApp");
myApp.service("clearCodemirror", function(cm){
Error I keep getting:
Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.2.6/$injector/modulerr?p0=angularApp&p1=Error…oogleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.2.6%2Fangular.min.js%3A29%3A56)
I only included the beginnings of each file so you guys wouldn't have to wade through tons of code. Where am I screwing up?
Thanks!
By calling angular.module("angularApp") from your 2nd file, you are recreating a angular module, and NOT getting a reference to the module that was created on the previous file.
There are a few ways to solve that. The simplest one (on my point of view) is to set your angular app to a window.VARIABLE.
window.myApp = angular.module("angularApp", ["ui.codemirror","ui.bootstrap", "ngSanitize", "ngRoute"]);
Then, from your 2nd file you can:
var myApp = window.myApp;
myApp.service("clearCodemirror", function(cm){
There are better ways to do that. However, this one you get you going. Cheers!
Hi you are not re creating the module you are getting the existing module by var myApp = angular.module("angularApp");
as the docs states :-
https://docs.angularjs.org/api/ng/function/angular.module
When passed two or more arguments, a new module is created. If passed only one argument, an existing module (the name passed as the first argument to module) is retrieved.
i tried with 1.3.14 , i didnt got any error, which version are you using:-

AngularJS - dynamic loading of external JS based on routes

I am trying to make a simple single page mobile app with multiple views and a next\back button to control each view. I am using the Angular Mobile UI library.
The basic mockup is as follows:
<html>
<head>
<link rel="stylesheet" href="mobile-angular-ui/dist/css/mobile-angular-ui-base.min.css">
<link rel="stylesheet" href="mobile-angular-ui/dist/css/mobile-angular-ui-desktop.min.css">
<script src="js/angular/angular.min.js"></script>
<script src="js/angular/angular-route.min.js"></script>
<script src="mobile-angular-ui/dist/js/mobile-angular-ui.min.js"></script>
<script src="app/app.js"></script>
<script src="app/firstController.js"></script>
<script src="app/secondController.js"></script>
<script src="app/thirdController.js"></script>
</head>
<body ng-app="demo-app">
<div ng-view></div>
<div ng-controller="nextBackController" class="navbar navbar-app navbar-absolute-bottom">
<div class="btn-group justified">
<i class="fa fa-home fa-navbar"></i>
<i class="fa fa-list fa-navbar"></i>
</div>
</div>
</body>
</html>
App.js is as follows:
var app = angular.module('demo-app', [
"ngRoute",
"mobile-angular-ui"
]);
app.config(function($routeProvider) {
$routeProvider.when('/', { controller: "firstController",
templateUrl: "views/first.html"});
$routeProvider.when('/', { controller: "secondController",
templateUrl: "views/first.html"});
$routeProvider.when('/', { controller: "thirdController",
templateUrl: "views/first.html"});
});
controllers = {};
controllers.nextBackController = function($scope, $rootScope) {
//Simple controller for the next, back buttons so we just put it in app.js
};
app.controller(controllers);
firstController.js will contain something similar to:
controllers.firstController = function($scope) {
//Do our logic here!!!
};
The problem is if you notice at the top of the HTML page I have to load all the controllers in. This is not scalable. I want each controller to be in it's own JS file and not have to statically load each one since the user may never even require that controller. Is there a way to dynamically load the actual JS file when switching routes? or can I stick a script tag at the top of my "first.html", "second.html", etc.
If I understand correctly you need to load specific scripts for each view? I am sharing this snippet from a personal project that uses ocLazyLoader a plugin that loads modules on demand.
var myApp = angular.module("myApp", [
"ui.router",
"oc.lazyLoad",
]);
then in your routing you could load dynamic JS / CSS files accordingly, in this example I am loading the UI Select plugin dependencies
myApp.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
// State
.state('demo', {
url: "/demo.html",
templateUrl: "views/demo.html",
data: {pageTitle: 'demo page title'},
controller: "GeneralController",
resolve: {
deps: ['$ocLazyLoad', function($ocLazyLoad) {
return $ocLazyLoad.load([{
name: 'ui.select',
// add UI select css / js for this state
files: [
'css/ui-select/select.min.css',
'js/ui-select/select.min.js'
]
}, {
name: 'myApp',
files: [
'js/controllers/GeneralController.js'
]
}]);
}]
}
})
If you're familiar with Grunt:
https://github.com/ericclemmons/grunt-angular-templates
Use Grunt and the above build task to create one .js from all views. Include a watch task listener over all html files in a views directory. Whenever a change is made to any partial views, a "$templateCache" entry is created with all of the html in the file and a url to alias the cache. Your routes will point to the partial views in the same manner, but the html files do not need to be present. Only the .js file with the templates. The beauty of this is that it loads once and is available on the client side for the entire session. This cuts down on http calls and your traffic can be reduced to web service calls, only.
This is the example of a template from the github link, above:
angular.module('app').run(["$templateCache", function($templateCache) {
$templateCache.put("home.html",
// contents for home.html ...
);
...
$templateCache.put("src/app/templates/button.html",
// contents for button.html
);
}]);
If you're not familiar with Grunt
Check it out. It's pretty invaluable for automating builds, minification, concatenation, transpiling, etc...
http://gruntjs.com/
Unless your app is MASSIVE, you should REALLY avoid serving small js files individually. This will noticeably slow down your app, even if you were to figure out a way to lazily fetch files on an as-needed basis as you suggest in your question.
A much better way to do this (and the way used and suggested by the AngularJS team) is to have a BUILD PROCESS (you should use grunt for this) concatenate all your javascript files, and serve them as a single app.js file. This way you can maintain an organized code base with as many tiny js files as you want, but reduce script fetching to a single request.
How to Install OCLazyLoad.
1. Download ocLazyLoad.js here
It can be found in the 'dist' folder of the git repository. You can also install it with bower install oclazyload or npm install oclazyload.
2. Add the module oc.lazyLoad to your application:
var myApp = angular.module("MyApp", ["oc.lazyLoad"]);
3. Load your JS files on demand, based on routes:
myApp.controller("MyCtrl", function($ocLazyLoad){
$ocLazyLoad.load('testModule.js');
}});`
With $ocLazyLoad you can load angular modules, but if you want to load any component (controllers / services / filters / ...) without defining a new module it's entirely possible (just make sure that you define this component within an existing module).
There are multiple ways to use $ocLazyLoad to load your files, just choose the one that you prefer.
Also don't forget that if you want to get started and the docs are not enough, see the examples in the 'examples' folder!
Quick Start
RequireJS can be really useful in this case.
You can declare the dependencies of your JS files using RequireJS.
You can refer this simple tutorial.
I think the best way is use RequireJS, as mentioned here Does it make sense to use Require.js with Angular.js? It is totally allowed and it will let you reach what you are trying.
here is an example code
https://github.com/tnajdek/angular-requirejs-seed
I am not sure how it works in standard angular, however, you could use angular-ui-router:
Controllers are instantiated on an as-needed basis, when their corresponding
scopes are created, i.e. when the user manually navigates to a state via a URL,
$stateProvider will load the correct template into the view, then bind the
controller to the template's scope.
https://github.com/angular-ui/ui-router/wiki

Create an AngularJS module if it doesn't exist

I have several directives and factories spread over several files but I want all of them to be included inside the same module. For example:
user-account.js
var userModule = angular.module("user", []); //I create the module here
userModule.directive("userPicture", ...);
user-transactions.js
var userModule = angular.module("user"); //I use the module here
userModule.directive("userPayment", ...);
The problem I have is for this to work I need to include the files in the right order, otherwise it won't work since the creation of the module is only done in user-account.js. I don't like this since users for these modules would need to know the proper order for it to work.
So my question is, how can I structure my modules creation + usage in an elegant way? I was thinking on creating some kind of Singelton helper to create the module if it doesn't exist but I don't love the idea. Any other ideas?
Don't mix the user module and the user-account in the same file.
app.js:
angular.module('myApp', ['user']);
user.js:
angular.module('user', []);
user-account.js:
angular.module("user").directive("userPicture", ...);
user-transactions.js:
angular.module("user").directive("userPayment", ...);
And then in your index.html:
<!-- modules -->
<script src="js/app.js"></script>
<script src="js/user.js"></script>
<!-- directives -->
<script src="js/directives/user-account.js"></script>
<script src="js/directives/user-transactions.js"></script>
I would suggest using requirejs in that case. Then you won't have to worry about ordering of your script files.
I am following the style from the book Mastering Web Application Development with Angularjs, the link is the whole example explained in the book.
The main idea of this style is
1. Dived code by businsess feature instead of by type;
2. Put everything from one module into one file, like:
// myApp.js
angular.module('myApp', ['user']);
//user.js
angular.module('user', [])
.directive("userPicture", ...);
.directive("userPayment", ...);
//index.html:
<script src="js/app.js"></script>
<script src="js/user.js"></script>
Why doing that is no matter directives, service or controllers, they are talking to each other, in one file you don't need to switch files.
Yes, you may bloat up the model file, but it is good sign to separate into another model.
I am using that style in my projects, and I found the code much readable than before.

Categories

Resources