loading multiple modules in angularjs - javascript

I'm constantly getting this error -
https://docs.angularjs.org/error/$injector/nomod?p0=interactive-main
The project structure (with multiple people developing and all new to angularjs) looks like this -
public
|--css, font-awesome
|--js (where angular.min.js and other jquery libraries are)
|--views (where html for each pages are)
|--myHTMLcontents
|--js
index.html
The index.html has it's own data-ng-app name and it's used in the app.js file.
I have my HTML files in the views folder, and the corresponding js files are in the views folder also.
I tried to create with
angular.module('myApp').controller(....
But I guess you're supposed to only create angular.module once (which is in the app.js), but I'm still unsure how to add 'myApp' in app.js.
I tried to do this:
(function () {
angular.module('data-ng-app Name', [
'ui.router', // Routing
'oc.lazyLoad', // ocLazyLoad
'ui.bootstrap', // Ui Bootstrap
'myApp'
])
})();
The nodejs server doesn't throw error, but nothing shows on the page (after I added 'myApp').
How do you solve this?

You need to create the module 'myApp' once and run it in app.js.
below is an example.
angular.module('myApp', []).run()
And then in your controller
angular.module('myApp.controllers', []).controller('RegisterCtrl', function () {});

First make sure your declare the myapp module file in your index before inject it into an other one :
<script src="js/myapp.js"></script>
<script src="js/my-module-injecting-myapp.js"></script>
Then two ways :
The first one is directly calling the module, by the way you did :
angular.module('myApp').controller(....
The second and what I used to do is declaring it as variable:
var myAppModule = angular.module('myApp', []);
Then to declare a controller, service , whatever, just call the variable:
myAppModule.controller("myAppController", function(){...
One last thing, I don't know if was an example but do not declare your module name with space :
angular.module('data-ng-app Name', [....
should be :
angular.module('myModuleNamewithoutSpace', [....

Related

Angular module declaration

I am trying to add 'base64' module to my Angular page controller.
Until now I have declared my controller like this:
angular.module('app').controller('newProjectController', newProjectController);
now what I should be doing looking at the git (https://github.com/ninjatronic/angular-base64) is
angular.module('app', ['base64'] ).controller('newProjectController', newProjectController);
However, what happens is that my view is just empty. It does not give any error message, but the view is rendered empty. I have included the js file in my index.html page, before using the controller.
The same problem persists when I use
angular.module('app', [] ).controller('newProjectController', newProjectController);
so the 'base64' module cannot be the problem in this...
Any ideas of what's going wrong? I am on Angular version 1.4.1.
first define module
angular.module('app',['base64'])
second define controller by referencing to defined module
angular.module('app' ).controller('newProjectController', newProjectController)
third make good tea ))

How to define controllers in multiple files - AngularJs

I am trying to define controllers in separate files, but I'm getting the error:
transactionsController not a function got undefined
File structure
I have added files in this sequence
1- common.js
2- transactions.js
Common.js
In common files I have defined
var app = angular.module("spModule", ["ngMessages", "ui.bootstrap"]);
Transactions.js
angular.module('spModule').controller('transactionsController',
['$scope', '$http', function ($scope, $http) {} ]
);
HTML FIle
<body ng-app="spModule" ng-controller="transactionsController">
First, you should get rid of the global app variable. This is not necessary. Second, you have to understand the principle of the angular.module() method.
Using angular.module() with two parameters (e.g. angular.module('my-module', [])) would result in setting a new module with its corresponding dependencies. In contrast, when using angular.module('my-module') the corresponding module is looked up internally and returned to the caller (getting).
The means when you first define you application you might just create the following files and structure.
app.js
angular.module('myApp', []);
FirstController.js
angular.module('myApp').controller('FirstController', function () {});
SecondController.js
angular.module('myApp').controller('SecondController', function () {});
If you now include these files in your html document in this particularly order (at least app.js has to come first), your application works just fine with two separate controllers in two separate files.
Further readings
I can recommend the AngularJS Styleguide on modules for getting more ideas on this topic.
You Can put this controller in seprate file like mycontroller1.js
app.controller('myController', ['$scope',function($scope)
{
$scope.myValue='hello World'
}])
Same like this you can create new js file 'myNewcontroller.js' and can put new controller :
app.controller('myController2', ['$scope',function($scope)
{
$scope.myValue='hello World'
}])
Hope this will help you :) Cheers !!
You can do this stuff by creating modules. Create module and respective controllers. And inject that module to the main app module.
Transactions.js
(function() {
'use strict';
angular.module('tmodule', []);
})();
(function() {
'use strict';
angular.module('tmodule').controller('transactionsController', ['$scope', '$http',
function ($scope, $http){
}]);
})();
Now inject the "tmodule" to your Common.js file-
var app = angular.module("spModule", ["ngMessages", "ui.bootstrap","tmodule"]);
Load your common.js first. Move ng-app directive to <html> tag. Change transaction.js to:
app.controller('transactionsController', TransactionsController)
TransactionsController.$inject = ['$scope','$http']
function TransactionsController($scope, $http) {
};
Just for fun. Let me know what happens.

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

angularjs defining services for the same module in different files

I have two files in which I define services in my angular app, but when I try to use them both in my directive, I get an error saying the service provider is not found for whichever directive I define second. It seems like one service is overwriting the other. If I change the module definition in service2.js to myapp.services2, then it works. I would think I could add multiple factories to the same module this way. Can someone point out what I'm doing incorrectly?
service1.js:
var services = angular.module('myapp.services',[]);
services.factory('Service1', function() {
// service code
});
service2.js:
var services = angular.module('myapp.services',[]);
services.factory('Service2', function() {
// service code
});
mydirective.js:
angular.module('myappdirective', []).directive('myapp', ['Service1', 'Service2',
function(service1,service2) {
// directive code
}]);
This is from the docs:
Beware that using angular.module('myModule', []) will create the module myModule and overwrite any existing module named myModule. Use angular.module('myModule') to retrieve an existing module.
Found here:
https://docs.angularjs.org/guide/module
This is possible, however will be error prone, hence not recommended
Make small modification to what you are already doing
Just do not re-declare the module variable in other files other than service1.js or put the module definition to a file of its own and include these JS file in the order of Module.js, services.js, directive.js then it will work

migrating angular to angular2 without changing project structure

i had my web app and cordova mobile app running now on angular 1 for about 2 years now, as application grow bigger we wanted to migrate our next version of app to angular 2.
current project is structured like following
----/root
|__app
|____app.js
|____app.css
|____index.html
|____app.common.directives.js
|____app.common.services.js
|____Page1
|______Page1.js
|______Page1.css
|______Page1.service.js
|______Page1.html
|____Page2
|______Page2.js
|______Page2.css
|______Page2.service.js
i had gulp building my app like so
it concat all js files into build/build.min.js
it concat all css files into build/build.min.css
cache all html in app folder and append it to build.min.js using templateCache (angular1)
copy index.html from app folder to build folder.
run watch server root # /build
This setup was very useful for us since when ever we are working on a new Module (a page essentially) all we have to do is create a new folder, drop a js and html file, and we are done !
example Page1.js
angular.module('mainApp')
.config(function($httpProvider, $stateProvider) {
$stateProvider.state('Page1', {
url: '/Page1',
controller: 'Page1Ctrl',
controllerAs: 'Page1',
templateUrl: 'Page1/Page1.html'
});
}).run(function($rootScope) {
$rootScope.sideMenu.push({
link: 'blog',
title: 'Announcements',
icon: 'bullhorn',
sideMenuOrder: 1
});
})
.controller('BlognewPost', function($server, $http, $scope,$state) {
var self = this;
this.method1 = function(){};
this.var1 = 'Hello Angular';
});
as you can see every module define its own routes, add it self to $rootScope.sideMenu -which is used in index.html to show sidemenu- and defines its own controller.
and our app.js was the main app file which wire connect modules/pages together, yet it was important to keep app.js un aware of how many pages/routes our app has.
angular.module('mainApp',['ngAnimate','ngMessages', 'ngAria'])
.config(function() {/*...*/})
.run(function($rootScope) {
$rootScope.sideMenu = [];
});
index.html is something like.
<html>
<ul id="side">
<li ng-for="item in $root.sideMenu" ui-sref="item.link">...</li>
</ul>
<ui-view id="content"></ui-view>
</html>
Question:
now with new angular2 component structure. is there a way we can migrate our old app while keeping same structure and build system ?
is it possible to define all routes in the components without root component have any knowledge of its existence ? -in above example you can see when ever we needed to add a page, we never touch app.js, we just create a new folder, and add the config, routes, run, and controller in its own folder.
our app is composed of 16 root pages making around 500k character compressed. should we rewrite the whole thing at once, or is there a way to migrate page by page ?
i see in angular2 starter component takes templateUrl config to point to template, is there a way to make typescript include the templateUrl html file as a string 'behavior like what templateCache used to do in angular1' ?
#Component({
selector: 'my-app',
template: string // OR templateUrl: 'page.html'
//what i need is something like template: require(page.html) so that my app html would be cached in js.

Categories

Resources