I come from the world of Backbone and JavascriptMVC. But I am really tempted to switch to AngularJS. So far, I have one big issue that keeps me from converting.
I create single page apps. Let's pretend it contains a tab module, a file upload module and a filelist module.
What I would do in Backbone is that I would split each of these as standalone modules
with their own view template, viewcontroller and so on. That way, I am able to use the module several places in my app. The modules don't know about anything other than itself.
How is this ment to be dealt with in AngularJS? Is it possible to create one angular.module per module (like for instance a tab module)?
I feel they tell a how to create many controllers within a module in their documentation. But that does not sound like what I need. Or am I misunderstanding some major concepts here?
EDIT:
I have done some more research. It looks like directives is what I am looking for. While a module in AngularJS represents the entire web app. So the mixing of the names 'components' and 'modules' is what confused me.
Am I on the correct path now?
You absolutely can define modules and you include your modules at the app level and then with dependency injection you allow your controllers to use what they need.
I have a proof of concept example for a small app I was working on to learn angular (it is pretty dirty and my playground):
http://plnkr.co/edit/1jGqaB00OznAUpyPZVT3
My app definition looks like this:
angular.module('myApp', ['ngResource','ui.bootstrap', 'myApp.services', 'myApp.servicesMovie', 'myApp.servicesSearch', 'myApp.servicesUtils', 'myApp.servicesMovieList'])
You can see I am including a bunch of different modules with my app and then an example of a controller that takes some services from the services module:
function SearchCtrl($scope, $rootScope, $route, $timeout, $routeParams, $location, SearchService, MovieListService) { etc }
Here is one of the module's defined (with its dependency too):
angular.module('myApp.servicesMovieList', ['myApp.services'])
With regards to templates, you can define these and include them with your route values:
$routeProvider.when('/view1', {templateUrl: 'view1.html', controller: ViewCtrl});
$routeProvider.when('/movie/:id', {templateUrl: 'movie-detail.html', controller: MovieCtrl, resolve: MovieCtrl.resolve});
$routeProvider.when('/search/:q/:p', {templateUrl: 'movie-search.html', controller: SearchCtrl});
$routeProvider.when('/searchlist/:url/:p', {templateUrl: 'movie-search.html', controller: SearchCtrl});
$routeProvider.otherwise({redirectTo: '/view1'});
}])
Or of course you can call them with ng-include
Yes, you're on the right path now. Another type of module in Angular are services. Services can be injected into any controller or directive (or even into other services) in a very clean manner.
Directives are primarily for reusable things that are visibly part of the UI, which is sort of reflected by the way they are put to use: by adding DOM elements/attributes.
Services are for more abstract things or things whose existence and behavior makes sense even without any directly corresponding user interface. The more logic you can sensibly shove into independent services, the more modular you application becomes and the more reusable the code is.
Controllers tend -- in my experience -- to be the least reusable and to be the first to grow complex and messy. (But that could just be me using them wrong.) The rule of thumb is to keep controllers as simple as humanly possible. Limit them to only pure business logic, and try to put most of that as well into services.
Angular does have a somewhat steep learning curve, but keep researching and then the different pieces will become apparent and fall into place. One resource right here on SO is this question: "Thinking in AngularJS" if I have a jQuery background?
Take a look at my post:
http://leog.me/log/large-angularjs-app-components
It's about a solution with RequireJS to partition the application in multiple modules that can be hooked together very easy.
Let me know if you find it helpful so I can put basic info here to avoid referring to a link instead of putting valuable content in the answer.
Related
I am implementing a functionality for (Add,update,delete & get,filter).
Currently Add View is used for add, update and delete. (Controller1)
Get View is used for get and filters. (Controller2)
Created routing for Add and Get Separately. So 2 controllers for each.
Now i have to call service for common config data , which is used in both the controllers.
which of the below design i should prefer.
Design 1
Combine both the controllers a one controller, put all the code inside.(including config data)
Design 2
One controller for Get ,filter
Second controller for Add, update and delete
common factory for Config data.
Am confused, which design i should prefer from all the aspects.
Please suggest.
Thanks in advance.
Its good practise to have "skinny controllers"
EDIT -
In AngularJS, controllers can sometimes become monolithic structures of mixed business and view logic, as it’s all too easy to house anything you need for the view inside the controller. It’s convenient, and it just plain works… until your application grows in complexity or needs unit tests.
So why do we want skinny controllers, anyway? In short, separation of concerns. Ideally, everything from services, to controllers, to directives, and more should be skinny, and achieving this is very possible in AngularJS. Each part should have a single responsibility and the controller’s responsibility should be to communicate between services and the view; i.e. its main concern should be view-model logic.
Aim to make your controllers skinny, as well as the rest of your application, by separating out view logic and business logic into controllers and services, respectively, and by taking advantage of routes and resolves.
You can read up in detail in this article & look at code examples
I feel like there is relatively little documentation on the "best practices" of how one should go about organizing AngularJS code. For example, in many of my web pages, i.e.
index.php
profile.php
editprofile.php
There are often many factories and methods that I need repeated. For example, profile.php,, editprofile.php, and index.php all need the factory userDropdown (to get the top navbar dropdown menu). However, some of them need "modified versions of factories". For example:
index.php needs a way to get all the users and their information
profile.php needs a way to get some users information
editProfile.php needs a way to get only one user information
What I mean is that (and the above was a poor example), is that often many .js files needs some modified "child" of a "parent" factory. I find it hard to scale my application because profile.php, index.php, and editProfile.php all refer to their own factories and methods, not a base file. Changes, improvements, errors, found in one factory and is corrected, will not propagate into other files (which I find very frustrating). I also don't want to write /copy/paste services and factories over and over again. Other issue I've had is that:
X.js file need some providers that Y.js file doesn't. However, both needs providers A and B, but X needs C and Y needs D. Is it bad for me to use the same "factory" and providers" for both of them (i.e. inject A, B, C, and D into both of them?) That's the problem I see with having a base factory of a factory to serve a lot of .js files. How much space or inefficiency is it to define providers or injectable services that you don't use?
How do I accomplish some scalable angularJS code to do this, or how do you guys go about organizing your angular code? And also, what about repeating HTML templates (i.e. repeating HTML code that needs to be used in almost every page? I've heard of some service called $templateCache but couldn't figure out how to use it.)
https://github.com/johnpapa/angular-styleguide This also has an example app but seriously read through his guidelines they seem to be exactly what you are looking for and have been a great resource for me as I've been learning to build bigger angular apps.
I am reading the source code for an app which reads as follows:
angular.module('graffio', [
'graffio.signupController',
'graffio.loginController',
'graffio.mainController',
'ui.router'
])
I have quite a few questions! So much confusion...
How is code loading these controllers which are defined later in the
code?
Why do I even need to state which controllers I want in my
app? Why can't I just have all the ones I declare?
Why does the angular documentation use the word 'injectable' so much? Isn't
injectable just the same as require?
With Angular, you can group as much or as little code into a module as you like. And you can compose modules together, like the author of the app you are looking at has done. The final module will have all of the services, config blocks, routes, controllers, directives, filters and so on that are in all of the modules it depends on as well as its own module.
This author has chosen to put each controller into its own module. Which is why the main module needs to depend on each of those modules. In my opinion, this seems like overkill, but it is what has been done, and all you need to do is understand it, not agree with it.
In answer to your other questions:
How is code loading these controllers which are defined later in the code?
When your code first runs, all the modules will be declared, and populated with directives, routes, controllers, services and so on. Nothing gets used yet. So long as when the code you have above is run, the other modules have already been declared then everything is fine (this may be done by a build process such as a Grunt task).
Then, when the document.ready event occurs, Angular looks through your HTML for an ng-app directive that says which module to load as your application. It then does what it calls the "bootstrap" process for that module.
Why do I even need to state which controllers I want in my app? Why can't I just have all the ones I declare?
Because this author has put each controller in their own module. If you put all the controllers you want into one module, then you don't need to declare them like that.
Why does the angular documentation use the word 'injectable' so much? Isn't injectable just the same as require?
Sort of. It is similar in that you are asking for a dependency by name and then using it.
It is different in that with require you can't typically modify what value is retrieved for a given dependency at runtime. With dependency injection, you can swap or modify dependencies at run time if you so choose (before your app starts properly and the dependencies are injected into the code using them).
This is perfect for testing, so that you can use a mock (fake) version of a dependency for testing purposes, instead of using the normal version. Think of a service that makes a call to get some data from the server and returns a promise. You can just create a mock version of that service that doesn't call to the server, just returns some test data immediately. This makes your unit tests fast, and means you don't need to be running your web server for them to work.
I am using angular seed project
https://github.com/angular/angular-seed
where should I put the services and directives ?
This is really totally up to you but there are some good recommendations on project structure here: https://docs.google.com/document/d/1XXMvReO8-Awi1EZXAXS4PzDzdNvV6pGcuaF4Q9821Es/pub
Typically my structure looks something like
app\scripts\user.js
app\scripts\todo.js
Where User.js would have a service and possibly multiple controllers in it... if the file gets too large then I break it up into parts.
The problem with grouping all services together and all controllers is that the services and controllers typically have a relationship (functionally). When you want to re-use the service/controller you are typically going to use them together, when editing one you usually need a reference to the other. This makes it easiest to find things and not have 1000 js files to include and manage in the dependencies and script inclusions.
Also when it comes time and you want to make a bower component out of one of the sections it's easier to see which parts need to be pulled out.
You can make a folder for each under app, so your project tree will look like this:
app/directives
app/services
So, I'm in the midst of my first major project with Angular. I have one controller that is doing a ton of the legwork, and it's reached the point where it's thousands of lines of JavaScript.
I'd like to break this up somehow, but I can't seem to find a solid example anywhere. The code is mostly made up of functions used to do calculations on objects, so directives and modules don't seem like the right answer, but I could be wrong there.
How are you guys organizing code in your large Angular projects? Should I just suck it up, or is there a sane way to split this into easy to scan files?
I suggest putting at least some of those objects and their related calculations into services, then inject the services into your controller(s). See the Sticky Notes Part 1 blog entry for an example of a service that encapsulates some data and provides methods to access/manipulate that data.
See if you can break up your controller into multiple controllers, one for each view. A view can be as large as a page, or just some chunk/block on a page.
To quote from a google group post I saw recently: "I prefer to think of angular controllers as dumb apis/configs for my views and leave all the heavy lifting to services." -- reference
There are a few things that you need to ask yourself when you are in a controller.
Are you doing any DOM manipulation in the controller? This is a definite NO. Dont ever do that. It always belongs in the directives department.
Are you writing any Business Logic in your controller? That too is a NO. Your Business logic should in most cases exist in a Service. That is the right place for it.
Now, have a look at your controller. Is it devoid of these 2 things and still larger than 1000 lines? It is highly unlikely, but even if it somehow is happening, then consider breaking down your controller into smaller controllers. This breaking of controllers have to be done based on the view.
To sum things up, your controller is just a place where you glue up the business logic and your views in the HTML. It should technically never contain anything other than these glues.
I usually create a Util factory (seems to be the way to go now in Angular rather than services) and have it return any shared logic as a set of methods.
https://gist.github.com/lamba/c275f5f010090632209e