Loading One Controller Per View AngularJS - javascript

I have an Spring + AngularJS Web Application with the following angular file structure.
mainmodule.js - where all config and routing's are
controller1.js
controller2.js
my main page is home.jsp where I imported all these files. As project goes bigger, I guess we have little over 50 files overall. So instead of dumping them in home.jsp, I would like to load them in it's corresponding view files. But when I tried to load controller1.js in corresponding JSP file, I get the below error.
[ng:areq] http://errors.angularjs.org/1.4.4/ng/areq?p0=dashboardController&p1=not%20aNaNunction%2C%20got%20undefined
Can someone help me identify what is the issue and how can I achieve this?
BTW I am using ui-router instead of default ngRoute.

One way of dealing with that scenario is to define a resolve property on each route and assign it a function that returns a promise. The function can handle dynamically loading the script containing the target controller and resolve the promise once the load is complete. For example:
$routeProvider
.when('/customers',
{
templateUrl: '/app/views/customers.html',
resolve: resolveController('/app/controllers/customersController.js')
});
But the best solution to your problem would be to use RequireJS framework with AngularJS for dynamically loading controllers per view.
There is very interesting source that explains about this : http://weblogs.asp.net/dwahlin/dynamically-loading-controllers-and-views-with-angularjs-and-requirejs
RequireJS official website: http://requirejs.org

Related

Angular Routing and Paths

I have a group of images at my root level and I also have a page called Help. If I navigate to rootspace/Help angular knows to get the images from the root repository, but if I change it to rootspace/Help/ then angular thinks the files are in a folder 'Help' that doesn't exist. I need the extra slash because I want to put more information after it.
How can I maintain '/Help/' without angular thinking this is part of the path it needs to find resources?
How are you getting the images? I'd recommend creating a resouce, this way angular will always know where to find the images if you provide a base url. It will also be easy to configure later on if you change the location of the images.
Example code:
angular.module('resources', ['$resource'])
.factory('Images', function($resource) {
return $resource(baseUrlGoesHere + '/images', {}, {})
})
Then you can inject the resource into your controller and call Images.get()
BTW, you probably can't use the code as is, I think the injection of $resource will fail but I'm not sure.

Angular directive to load JS files for the other directives

I'm trying to minimize js/css/html footrpint for the user and to load only the files really needed. I've utilized RequireJS for that.
For my templates I'm trying to implement someting similar to
using section in C# or ///< reference path='...' > in TypeScript
But somehow depending on my template content it does or doesn't instantiate depends-on directive depending on template I have:
Works:
<depends-on path="..\..\test"></depends-on>
<login-form></login-form>
Doesn't work:
<depends-on path="..\..\test"></depends-on>
<login-form></login-form>
<other-directive></other-directive>
Doesn't work:
<div>
<depends-on path="..\..\test"></depends-on>
<login-form></login-form>
</div>
I'm obviously missing the way Angular parses and processes templates.
Is there a way to achieve what I'm trying to do?
OK, the problem was that it didn't wait until all directive template depends on are loaded. To ensure dependencies are loaded, dependent code should be in callback passed to require function.

updating angularjs libraries causes error in angular.bootstrap()

We have a legacy framework that we're looking to be able to do some major updates to soon. As part of this, we're working at bringing all our library files up to date. During this process, we upgraded angularjs from 1.0.7 to 1.3.13. Suddenly, we're getting a show-stopping error.
Error: [ng:areq] http://errors.angularjs.org/1.3.13/ng/areq?p0=MainCtrl&p1=not%20a%20function%2C%20got%20undefined
The question is: Why does this error happen when we upgrade to the newest library, and how am I supposed to do this now? I will add the most relevant lines of code below, and I can add more as requested, but it's kind of complex and I'm not sure how to break it down to something easy to stick into here.
The error occurs at angular.boostrap() The relevant code shows like so:
angular.module('app',['DataTools','ClientDataTools']);
angular.bootstrap(document, ['app']);
Main Ctrl is defined as such:
function MainCtrl($scope, $compile) {
The file structure is as such:
load.js
run.js
dataTools.js
load / controllers.js
load / config.js
load / ClientDataTools.js
load / libraries.html
The automatically generated html loads up along with the js code found in load.js. This first thing it does is load up libraries.html, which contains the imports for run.js, dataTools.js, controllers.js, and ClintDataTools.js. The code in load.js then calls a function defined in run.js. This function loads config.js and applies the settings there while going through and using jQuery to add angular tags to the form found in the automatically generated html. It then runs the angular.module() and angular.bootstrap() commands.
controllers.js holds the MainCtrl declaration. config.js is just a json string. dataTools.js and ClientDataTools.js holds the directives used by the angular - this error still happens even when removing the directive files, so I don't think they're part of it, but they are included here out of completeness of the issue..
And no, I can't just change the html in the form in the first place. I don't have access to it. It's automatically generated html to which we wish to add intelligent behavior like preventative data checking. It's an automatically generated form that we'd like to work a little more responsively. Please don't recommend just putting the angularjs markup into the html, and please don't ask why we can't touch the original html.
The way of declaring controller with
function MyCtrl() {}
has been deprecated - try declaring like
angular.module("app").controller("MyCtrl", function() {})

Umbraco 7 custom property editor using angular file upload

I am using angular file upload in a custom property editor for Umbraco 7.0.3. I am following this tutorial in order to create the editor.
I am quite new to angular, so my question maybe trivial for some of you: I cannot resolve dependency to file upload service in my controller soon enough. My HTML template looks like:
<div ng-controller="MyCustomController">
<input type="file" ng-file-select="onFileSelect($files)" multiple>
</div>
The controller function would need $upload service as an argument, however I inject that service at the beginning of the function:
angular.module("umbraco")
.controller("MyCustomController", function ($scope, assetService, $upload) {
assetsService
.load([
"/App_Plugins/MyCustomPlugin/angular-file-upload.min.js",
])
.then(function () {
alert('upload service loaded');
});
$scope.onFileSelect = function ($files) {
alert('file selected');
}
});
So, it is definitely not right this way. I was trying to load the upload service before the controller initialization, however it loads asynchronously, so the service cannot get defined before the controller anyway.
How can I declare my controller function only after the upload service is loaded, or how can I get a reference to the service other than an argument?
Thanks,
EDIT
The only solution I've found so far was to include the actual file upload codebase into the controller of the custom property editor. I used this paper as a starting point for my own codebase for its simplicity. However I am still looking for the 'proper' way of loading an external module in this case.
Include your code as a service instead.
The code angular.module line can take extra parameters if you see its documentation page. It is here that you should look to include any third party libs. For example, I use ngTable - an AngularJS wrapper around a jQuery sortable and filterable table plugin. To include its usage, I have to add it as a service to the current application's module like so:
var app = angular.module("umbraco", ['ngTable']);
All I then have to remember to do is to reference the scripts, and I can use the code as though I had included the body of the code itself. Therefore, I presume that you would reference your service JS files, and write your code to reference the service like this:
angular.module("umbraco", "MyCustomController");
I would however rename the code as services rather than controllers.
It's a steep learning curve for AngularJS, and even when you've used it a lot, there are a lot of common gotchas. I hope this explains it a bit more.

AngularJS: Resolve and lazy loading services

I'm using this method for lazy-loading the controllers/services required for each of my AngularJS routes.
Basically, for each route, I define the dependencies (e.g the controllers, services, etc needed), then a function is added to the resolve of the route definition for that route, that function dynamically loads the javascript files of the dependencies.
This works, however where I run into a problem is this. Suppose that I wanted to lazy-load a service called fooService for the route /foo. However, what if I also wanted to have fooService.getResults() added to the resolve for /foo? This gives an error because perhaps the fooService.js file is not loaded by the time the resolve function for fooService.getResults() is called.
Is there any solution to this?

Categories