I have just started working in angular.js and I have created separate angular applications (using ng-app) for separate modules of my application for modularity sake so that change in one module does not bring down the whole application.
Now, i am running into a issue of redirecting from a search form common across all modules to a particular page (in a specific module). I thought of saving the value in $rootScope, but while debugging, I found that $rootScope is per ng-app, so, it will not work.
Am I wrong in designing the application into separate angular applications and should I move everything back into one ng-app? or is my application structure correct and I should look for another way of passing value?
EDIT: - I think I did not provide enough detail earlier.
My application is structured as follows:
module1
- controller\controller-module1.js
- service\service-module1.js
- css\module1.css
- view\ <multiple html files>
module2
- same structure
I was actually using the service-module to make REST calls to the server till now, rather than sharing data.
All the modules are defined with their separate dependencies in app.js:
angular.module('Module1App', ['Module1App.controller','Module1App.service']);
angular.module('Module2App', ['Module2App.controller','Module2App.service']);
controllers and service of each module are defined in their respective controllers-module.js and service-module.js, which reside in different directories as per the structure above.
So, to include the controller and service of a particular module(of, say, module1), I declare the following in a view of that module
<script src="/APP_GUI/modules/common/service/services-common.js"></script>
<script src="/APP_GUI/modules/reports/service/services-module1.js"></script>
<script src="/APP_GUI/modules/common/controller/controllers-common.js"></script>
<script src="/APP_GUI/modules/reports/controller/controllers-module1.js"></script>
So, if I have to move all ng-controllers (defined in separate directories as per the module structure above) into one ng-app (app.js above), I will basically end up including all the controller.js and service.js in all the html views, which will basically mean that if there is an error in any one of the js files, my entire application will be down (i have tried it out).
So, unless I have misunderstood something, I cannot move all ng-controllers under a single app.js.
I am going to try out using shared services to share data.
Please let me know in case anybody has something to say on my conclusion.
I don't think using many ng-app is a good approach. I suggest you using many ng-controller in separate file instead.
You can keep variables inside objects instead of using $scope, which most tutorials you'll find online don't explain.
For example:
/// Define the app
app = angular.module('MyApp',[]);
///Add a cotroller
app.controller('MyFirstController', ['$scope', function($scope){
/// using 'this' you can write local properties
this.firstLocalProperty = 'first Value is acessible only in MyFirstController';
this.secondLocalProperty = 'second Value is acessible only in MyFirstController';
$scope.firstSharedAppProperty = 'This is Shared between all controllers in app';
}]);
app.controller('MySecondController', ['$scope', function($scope){
/// here you can use shared and local properties, you may access shared things in $scope
this.fistProperty = $scope.firstSharedAppProperty;
}]);
You'll see that
> MySecondController.firstProperty
'This is Shared between all controllers in app'
but
> MyFirstController.firstProperty
'first Value is acessible only in MyFirstController'
MyFirstController.firstProperty keeps it's original value because it's not shared.
Basically, you should use different controllers for different templates instead of using different modules. Using controllers, you may share items between them in the $scope variable. Or you can keep variables private using this reference inside objects.
Take a look in this article and you may understand better this way.
You should be using multiple controllers and then using a common service shared between your services. Services in angular are singletons, so they can be shared over and over and over again, and will be common across the board, including between applications if you inject the shared functionality as another application.
var app = angular.module('firstApp');
app.service('myService', function(){
var self = this;
return{
getValue: function(){return self.value},
setValue: function(value){self.value=value}
}
});
app.controller('firstController', ['myService', function(myService){.....}]);
app.controller('secondController', ['myService', function(myService){....});
var secondApp = angular.module('otherApp',['firstApp']);
secondApp.controller('otherController', ['myService', function(myService){.....}]);
more importantly, if its doing anything more than just storing values you can inject functionality for better testing!
Related
I was wondering what should be considered when creating Angular services in regards to which module to attach the services too.
For example
var app = angular.module('app', []);
//Add service to app module
app.factory('helloWorld', function() {
return {};
});
//Or create a module for the service, and include the module where needed
var helloWorldModule = angular.module('helloWorldModule', []);
helloWorldModule.factory('helloWorld', function() {
return {};
});
//Or attach is to an existing module that may need it
existingModule.factory('helloWorld', function() {
return {};
});
Should all services created be added to the app module, so I can ensure that I can access the service anywhere if I need to, or should I add it to only the modules that I know that will be using it.
I know that this may be subjective, and based on application structure, basically I am just wondering if it is ever a good idea to add all services to the app module.
As always it depends. If your service is an isolated service that can be shared across different applications and modules then the answer is yes.
If it is relevant only to your current module then no.
Try to maximise the cohesion. If you only have a solution or app it doesn't matter where you place the service, but if you have multiple solutions, maybe during a refactoring process you realise that some services make sense to put them together in the same module.
I have an application based on e.g. the Northwind database, in which I have built views for each of the different objects to maintain them CRUD-ly, using AngularJS views and the in typical file structure adopted by most devs.
I have an issue I would like to improve, firstly from all examples I have seen, you need to declare your controller on an index.html file. If one module that a user uses does not require, all the other controllers, is it necessary to load all controllers on the client side. Is there a better way to only declare controllers that are need per view?
Is this the normal behaivor of a Single Page LOB, to preload all necessary dependencies, whether required or not?
No. Don't declare your controllers in your HTML.
The less logic you add in your template, the more flexible your app will be.
The problem with including controllers in your HTML is that if some nested controllers have the same instance var (example foobar), then you don't know which one would be displayed :
<div ng-controller="firstController">
...
<div ng-controller="secondController">
...
{foobar}
Then, the best way is to work with modules and routes. With routes, you can tell AngularJS that your HTML should be controlled by aController.
I you are looking for a good app to start with, take a look at this one.
It has been developped by the AnguarJS team and shows some good practices to follow. You can notice that none of the HTML files contain a reference to a controller.
var myapp=angular.module('myAppln',[]);
I am new to angularjs. Why should we use [] in angular.module()? Could anybody please explain.
This is used for injecting dependency. Dependency Injection or DI is a software design pattern in which components are given their dependency instead of hard coding them within the component. This is also helpful in making dependency configurable and make components resuable & maintainable.
Components such as services & directives are defined using injectable factory
For example when define a service in angularjs we do like this way
var abc = angular.module('ngAppName',[]);
abc.factory('serviceName',['$http',function($http){
// Rest of code goes here
}])
angular.module('ngAppName',[])
It is more or less entry point for angular application & here we do not have any dependency so this is an empty array.
But take a look when we are defining our custom service.Here this service has dependency on $http which is predefined service offered by angular for ajax call.Our custom service(serviceName) has dependency on this $http, which we are injecting here
Another example with angular route
abc.config(['$routeProvider',function($routeProvider){
// Rest of code goes her
}])
The $routeProvider is what creates the $route service and it is provided by angularjs. While creating route we have to depend on $routeProvider. So we have injected it our code.
Hope this will be helpful for you.
if you go further in Angular.js then you will read that you can pass injectors and other stuff to module. So here api return in a manner that it receaves array of options. when you wont have any you just pass it blank []
Actually [] is an array with the dependencies that are required by the module.
I scaffolded a simple Angular app using Yeoman, and I've been playing with it ever since.
Inside the file app.js, which is the first one listed as a <script> inside index.html, I define the main module as:
angular.module('myMod', [])
.config(...)
Note the empty array of dependencies.
Now, when I want to, say, add a filter to this module, I create a myFilter.js file (which I load after app.js inside index.html); myFilter.js consists of:
angular.module('myMod').filter(...)
Note there's just one parameter to the module() function. If I pass the empty array of dependencies as a parameter to this module() function, really nothing appears on screen.
I've been playing with a bunch of other files which extended myMod with controllers, and passing [] as a parameter to the angular.module() function breaks my app every time.
It seems to me like I can only call angular.module() once using the second parameter, which may have some sense (how many times do I want to list my dependencies? What about consistency?). Is it that way?
If it is, is there some standard place where to list dependencies for a module?
angular.module("myModule",["dependencyA"]) will create a new module (this will crash if module allready exists.)
angular.module("myModule") uses an already known module.
This will also affect how you need to load the scripts in the index.html
You should declare your dependencies only once. In addition, it's best practice to keep all of your filters as a separate module that your app depends on, for example:
var myApp = angular.module('myApp', ['myApp.filters', 'myApp.directives', 'myApp.someOtherDependency']);
then, you would define your filters as a module that your app is dependant on:
angular.module('myApp.filters', []).filter(...)
Working on a module based app where depending on the user, I'll load a given template (view) as a module inside a common view. The problem is that the different views require different controllers and they one share a small set of common form inputs.
Based on a call to my server I'll get a JSON response containing what view/controller should be loaded for that user. This solution worked fine earlier as all my controllers were in the global scope:
$scope.corporation.payloadController =
// Contains the String "ComputerPayloadCtrl"
[window]data.corporation.payloadController;
Now however, after I have rewritten the applications to use the angular module design pattern, I get the following error (I no longer use [window]):
Argument 'corporation.payloadController' is not a function, got string
The controller is already defined, so I'm only looking for a way to reference it by String.
.controller('ComputerPayloadCtrl', ['PayloadService', '$scope',
function(PayloadService, $scope) {
$scope.payload = PayloadService.payload;
}])
The more I work with this problem, the more this entire approach I've chosen is bugging me. So if anyone has any suggestions on how to alternatively solve this I'll gladly hear it.
Edit: So I found a very simple workaround, but I'll let the question stand in case there is an actual way to do this.