I have a globale routes controller and want to create an additional controller for each page template.
It's done as follows:
var app = angular.module('myapp', ['ngSanitize', 'ngRoute']);
app.config(function($routeProvider){
$routeProvider
.when("/test", {
templateUrl: "./templates/test.html",
controller: "testController"
})
});
app.controller('test', function() {
//...
});
Question: how can I move the controller to it's own testController.js file? I tried it, but then the controller does not work anymore.
Which steps do I have to take if I extract the controller in its own file?
How can I get access to var app module variable from within testController.js?
Do I necessairly have to include each controller as new <script src="js/testController.js"></script> tag entry in my html templates? That would be cumbersome, as I want to split my application into many controllers, and that would result in many many imports.
You can access app by simply declaring it without dependencies:
var app = angular.module('myapp');
app.controller("testController", function() {
});
And yes, you need to include testController.js on every page that needs it.
Related
I am creating small application called puzometr. It is for educational needs only. I want to create this application using AngularJS. Also, I want to use RequireJS as module system.
I have strange problem. I created my test controller and I got problem: controller initialization fires two times.
Firstly, full code available here on GitHub (wait, don't click me, I will explain everything below).
So, problem is in myCtrl.js file. Here is code of this file:
define(['angular'], function (angular) {
var module = angular.module('main.myModule', []);
module.controller('main.myCtrl', function ($scope) {
console.log($scope.$id);
$scope.bob = function () {
}
})
});
It is included in main/controllers/controllers.js by this:
define(['app', 'main/controllers/myCtrl'], function (app) {
var module = angular.module('main.controllers', ['main.myModule']);
});
This file included in main.js by this code:
angular.module('main', ['ngRoute', 'main.services', 'main.controllers', 'main.directives']);
And main.js is included into app.js:
var app = angular.module('myApp', ['ngRoute', 'main', 'common']);
So, I incidentally noticed, that function definition in myCtrl controller fired two times. I put console.log there and saw this:
Can you please explain me why is this happens? Why controller is being initialised two times?
Also, I have this in ng-inspector:
So one scope is created as child for another scope. Notice, that scope with id 3 has correct controller name.
If you use ng-route to register controllers and bind them with views, then don't add them again using attributes in your html files.
I have an app that which has a load of scripts loading initially and the list is growing as development goes on. I want to lazy load scripts which contain controllers as and when needed. I am using OcLazyLoad along with ngRoute for the routing option (i did try ui-route which actually had the same end result but was causing other app issues). The lazy load and routing is working fine, scripts and views are only loaded when needed, but the issue is the controller is not being loaded (Argument 'caseReviewController' is not) so it's as though the controller does not exist.
Here is a simple version of what I have in my app.js file...
var app = angular.module('dashboard', ['oc.lazyLoad', 'ngRoute', 'LocalStorageModule']);
app.config(function ($ocLazyLoadProvider, $routeProvider, localStorageServiceProvider) {
$ocLazyLoadProvider.config({
loadedModules: ['dashboard'], modules: [
{
name: 'caseReview',
files: ['js/controllers/case-review.js']
}
]
});
$routeProvider
//other routes here...
.when('/case-review', {
templateUrl: 'views/case-review.html',
controller: 'caseReviewController',
resolve: {
loadModule: ['$ocLazyLoad', function ($ocLazyLoad) {
return $ocLazyLoad.load('caseReview');
}]
}
})
});
In the seperate case-review.js file I have a simple controller
app.controller('caseReviewController', function($scope, localStorageService, $route){
//do stuff
});
This controller is not being found or executed but the view and js file are being lazy loaded as expected. Any help would be great.
Thanks.
In your separate case-review.js, you must get the reference of app.
angular.module('dashboard').controller('caseReviewController', function($scope, localStorageService, $route){
//do stuff
});
As you've mentioned it's in separate file, it may not know about the app variable. It's better to get the reference of the angular module in the separate file.
This must solve your issue.
I'm a beginner in the AngularJS environmnent. In the interest of my company, I would like to combine the power of the Angular framework with the Dustjs templating engine.
The problem is : Dustsjs is compiling files to .js files (I have a Grunt task which is doing that for me in my public folder), not in .html. And, in the documentation of $routeProvider, the 'templateUrl' or 'template' parameters are looking for .html templates.
My app.js :
var app = angular.module('myApp', []);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', {
template: 'views/myView.js',
controller: 'HomeController'
});
}]);
As you can imagine, I have a weird result since my .js is injected without being parsed.
http://i.stack.imgur.com/5JkRx.jpg
So, my two questions are :
- Am I doing it right to put the .js file path inside the template of routeProvider, or is there another way to get and correctly display the view? In short, what did I do wrong?
- Are there any best practices for combining these two technologies?
Am I doing it right to put the .js file path inside the template of routeProvider, or is there another way to get and correctly display
the view? In short, what did I do wrong?
No you are not right in putting the .js file path. Angular expects it to a HTML markup.
template: '<div>content</div>',
and
templateUrl : 'views/myview.html'
would be acceptable values.
Are there any best practices for combining these two technologies?
One of the ways to go would be to use dust templates as the outer template and let angular routeProvider take care of rendering the dynamic content to be parsed by angular. For example,
home.dust
<html>
<head>
<title>{page_title}</title>
</head>
<body ng-app="myApp">
{>header/}
<div ng-view></div>
{>footer/}
</body>
</html>
header.dust
<div id="menu">Menu</div>
footer.dust
<div id="copyright">Footer</div>
view/myView.html
<div id="content">Hi ((username))</div>
app.js
var app = angular.module('myApp', []);
app.config(['$routeProvider', '$interpolateProvider', function ($routeProvider, $interpolateProvider) {
//This is required as dust templates also '{' and '}' for interpolation
$interpolateProvider.startSymbol('((').endSymbol('))');
$routeProvider.when('/', {
templateUrl: 'views/myView.html',
controller: 'HomeController'
});
}])
.controller('HomeController', function($scope){
$scope.username = "John Doe";
});
I am getting started with AngularJS, and as I understand, I can have different controllers for different sections of my web page. I am having the problem getting it work. I have two sections of my page and corresponding to each one ng-controller - JSFiddle. Only the section that come first works. For example currently, app1 works fine, but when I move it below app2, only app2 works fine. What could be wrong? Much appreciate any explanation regarding why this behavior and any links.
You can have multiple controllers, but you cannot have multiple ng-app directives on the same page. This means you should only have a single ng-app directive in your html that points to a single module that will be used in your application.
You then define this module and define all your controllers in this module:
var app = angular.module('app', []);
app.controller('TextController', function ($scope) {
//Controller Code Here
});
app.controller('ItemController', function ($scope) {
//Controller Code Here
});
If for some reason you want to have controllers in separate modules, you can still do that, and include those modules as dependencies of your main module:
var items = angular.module('items', []);
var text = angular.module('text', []);
var app = angular.module('app', ['items', 'text']);
text.controller('TextController', function ($scope) {
//Controller Code Here
});
items.controller('ItemController', function ($scope) {
//Controller Code Here
});
Generally you don't need to have a module for each controller. Modules are used to group related pieces of functionality together to make it easy to take that and re-use it in another application.
Here are links to some examples:
Single Module : http://jsfiddle.net/36s7q/4/
Multiple Modules: http://jsfiddle.net/36s7q/5/
Notice how in both example there is only a single ng-app on the page.
Take a look at this, I changed a lot around. http://jsfiddle.net/36s7q/6/
No need for two app modules on the page to achieve two controllers, you can have multiple controllers within the same module. I also simplified the syntax. Take a look.
var items = angular
.module('app1', [])
.controller('ItemController', function($scope) {
$scope.items = [ {
title : 'Pencil',
quantity : 8,
price : 4.2
}, {
title : 'Pen',
quantity : 2,
price : 5.2
}, {
title : 'Watch',
quantity : 3,
price : 10.2
} ];
})
.controller('TextController', function($scope) {
$scope.text = {
message : 'Welcome!!'
};
});
Here is how you have multiple controllers:
var app = angular.module('MyApp', ['ngMaterial', 'ngMessages', 'material.svgAssetsCache']);
app.controller('DemoCtrla', DemoCa)
.controller('DemoCtrlb', DemoCb)
.controller('DemoCtrlc', DemoCc);
function DemoCa($mdConstant) {
// function here
}
function DemoCb($mdConstant) {
// function here
}
function DemoCc($mdConstant) {
// function here
}
I hope it helps ;)
Instead of answering your actual question, i suggest usage of routing.
Be aware: This technique is not needed to solve your issues. However, you may want to know about it for future projects.
If i got you right, all you want to do is using a different controller / view for a specific section of your page.
To achieve this, create a single application module (remember, Angular applications are SPA's). Then, you could define some routes and tell Angular what to use when one of them is demanded:
var app = angular.module('app', ['ngRoute']);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/', {templateUrl: './partials/views/root.html', controller: 'rootCtrl'}}).
when('/section', {templateUrl: './partials/views/section.html', controller: 'sectionCtrl'}}).
otherwise({redirectTo: '/'});
}]);
Further reading: http://docs.angularjs.org/api/ngRoute
Be aware that the latest stable version of Angular requires the ngRoute module in order to use the routeProvider.
I'm starting with angular, how could I break alll the code from one app into many files?, I watched the 60ish minutes intro, and they mentioned that I could do this without requirejs or any other framework.
Lets say I have something like this that works just fine:
var app = angular.module('app', []);
app.factory('ExampleFactory', function () {
var factory = {};
factory.something = function(){
/*some code*/
}
return factory;
});
app.controller ('ExampleCtrl', function($scope, ExampleFactory){
$scope.something = function(){
ExampleFactory.something();
};
});
app.config(function ($routeProvider) {
$routeProvider
.when('/',
{
controller: 'ExampleCtrl',
templateUrl: 'views/ExampleView.html'
})
.otherwise({ redirectTo: '/' });
});
What if I wanted to have it in separate files? like this
File One:
angular.module('factoryOne', [])
.factory('ExampleFactory', function () {
var factory = {};
factory.something = function(){
/*some code*/
}
return factory;
});
File Two:
angular.module('controllerOne', ['factoryOne'])
.controller ('ExampleCtrl', function($scope,ExampleFactory){
$scope.something = function(){
ExampleFactory.something();
};
});
File Three:
angular.module('routes', ['controllerOne'])
.config(function ($routeProvider) {
$routeProvider
.when('/',
{
controller: 'ExampleCtrl',
templateUrl: 'views/ExampleView.html'
})
.otherwise({ redirectTo: '/' });
});
File four:
var app = angular.module('app', ['routes']);
I've tried it like this and it doesn't work.
Can I do something like this and just have a script tag for File Four in the main view? or do I have to have one script tag per file?.
Thanks for the help guys.
AngularJS does not currently have a script loader as part of the framework. In order to load dependencies, you will need to use a third party loader such as RequireJS, script.js, etc.
Per the Docs(http://docs.angularjs.org/guide/module#asynchronousloading):
Asynchronous Loading
Modules are a way of managing $injector
configuration, and have nothing to do with loading of scripts into a
VM. There are existing projects which deal with script loading, which
may be used with Angular. Because modules do nothing at load time they
can be loaded into the VM in any order and thus script loaders can
take advantage of this property and parallelize the loading process.
...or, as #xanadont explained, you can add <script> tags to your page for every file.
You must have a
<script src="file.js"></script>
per each file that you're using. It should work once you have all the references in place.
Or ... check out this article for a way to roll-your-own runtime resolution of controllers.
You've got to separate the idea of downloading from the idea of loading and executing in-memory. Use Yeoman/grunt or similar build tools to manage the process of adding individual files to the project for Angular's various modules controllers, directives, services, etc. that are attached to those modules. Then, at build-time, the files will be minified and concatenated for a speed/bandwidth improvement that's vastly superior to lazy-downloading of individual files.
Once you've dealt with the files, Angular handles the rest, executing dependencies only when they're actually needed.
In the example above, #Jose, your problem was that you're not attaching your dependencies properly to the original module. You're creating new modules and burying the dependencies inside of them. In the first version, you used var app to cache the reference to the module called 'app' and then did app.controller(), etc. So, you're calling the .controller() method on the app module.
But in the second, you still need to attach those dependencies to the main app module. To do that, you need to call angular.module('app') to access the original module, then you can chain a call to .controller() or .directive() from that module, once you've retrieved it.
Bottom-line, use Angular's constructs for the loading of Angular dependencies. If, after you've gotten all of that out of the way, you still want to use Require for loading third-party scripts, go ahead. But I recommend testing first to see if you're actually adding value.