AngularJS module dependencies - how many times can I list them? - javascript

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(...)

Related

about module in the angular

I am new in this field and reading about one project code. Here are two file.
https://github.com/PatrickO10/meetUp/tree/master/app/dashboard
In the first file:
(function(){
'use strict';
angular.module('app.dashboard', ['firebase']);
})();
In the second file, similiar code appears again
https://github.com/PatrickO10/meetUp/blob/master/app/dashboard/dashboard.controller.js#L4-L6
I see many code write like var app=angular.module(...), if you write in way of first file, how could you use the module again? and why you write it in this way?
I also want to know why you write the first file here, why don't you put all things in the second file.
Thanks.
When you define your module in angular, you have to define an array as second parameter with the list of modules your module depend on (or an empty array if is not depending on anything).
When you use your module in angular, you skip this second parameter.
These are the two cases in your code.
You could put everything in same file, but it is considered a general good practice to keep individual files for different controllers/services/directives (or even the definition of the module).

angular.js modularization - multiple ng-apps?

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!

Angular modularization with dynamic route and dynamic dependency

I have a question about get routes and dependency of the main module dynamically. I've been researching this for over 3 days now and haven't found a satisfactory answer. I have found something which seems to come close but it's not what I'm looking for, I do not want to lazy-load my modules or just set routes dynamically .
so I will try to explain my needs as clearly as possible:
there is a folder that name is shared in my project that contains some reusable modules. I need my app.js to realize routes by drag and drop modules and dependency without manually change!
Does anyone have a solution for this?
Thank you for your time and help
This snippet can address your dynamic module resolution requirements.
create deps array and then pass it to "define" method (registered by requirejs).
put all of your related dependencies in the same folder. for each module, you can create a separate js file. every time that I need a new service, I create a separate js file for that service and place it to the 'services' directory and finally append the new service name to the dependency array. and new module is ready to use.
(function () {
(function (deps) {
window.app.utils.appendPrefixToPaths(window.app.paths.services.out.get(), deps);
deps.unshift("2.services/directive");
deps.unshift("2.services/view");
deps.unshift("2.services/preference");
deps.unshift("2.services/alert");
deps.unshift("2.services/materialDataTable");
deps.unshift("2.services/security");
deps.unshift("2.services/theme");
deps.unshift("1.directives/_");
define(deps, function (obj) {
return obj;
});
})(window.app.services.fileNames.get());
})();

Require dependency only when backbone view is loaded

I am using Backbone with Layout Manager and RequireJS.
View1 depends on 2 dependencies as can be seen below.
The application also has a similar view
named View2, which depends only on 'jquery.fileupload', unlike View1, which has 2 deps.
define(['jquery.fileupload', 'jquery.fileupload-ui'], function (dep1, dep2) {
var View1 = Backbone.View.extend({
...
});
return View1;
});
The problem is that 'jquery.fileupload-ui' (second dependency) seems to be loaded/evaluated by requireJS even if I don't visit a view that depends on it and that causes some plugin errors (I am using basic fileupload plugin in one view, and extended fileupload plugin in another view). It looks like define() pre-loads modules right away.
How can I avoid loading the second dependency at app initialization and load it only inside my view?
I think I could nest require() call into define for View1,
but I am not sure how then I can return a value if calls are nested.
Any time you module load the view1 module, 'jquery.fileupload-ui' will be loaded. If you only need this module in certain cases when you module load view1, you could have view1 require() in 'jquery.fileupload-ui' only if a certain code path is reached.
You can do this by adding a require(['jquery.fileupload-ui'], function(jqui){...}); in the specific method within view1 where you need the library.
I am not sure if this answers your question, but I think it may.

requirejs loading async templates module pattern

I just decided to try require.js for the first time and for the most part, it works fine - until I get to the point where I try to handle template loading dynamically.
basically, i have a requirement that the app should not proceed until the templates have all been loaded and made available.
to that effect, a module 'templating' has been created. it imports a definition of an array of templates (already available) that it needs to load - require - before it returns.
I am pretty sure this is probably an anti-pattern so how would you fix it?
app -> requires "templating"
define templating ->
- loop through an array of templates and dynamically create a list
- define all templates (via text!) so later we can require("template-name")
- also tried, require all templates
What I observe is that the templating module loads and becomes available to the app before all the templates are loaded.
The XHR fetching the templates follows afterwards.
How do i prevent the module from returning before all the texts load and compile? pseudo code or links to examples would be fine.
We actually had one solution early on in a project and then moved to another one.
[1] Synchronization - Because we're using jQuery in our app we have the jQuery Deferred object available for use throughout the app. I created one instance of Deferred which only had its .resolved() called when all of my templates were loaded. Then each time I tried to use a template I had it wrapped in code like this:
$.when(cache.templatesLoadedPromise).done(
function () {
// Render the view.
$("...").html($.tmpl(cache.template, jsonData));
});
Then none of the renders would happen until the templates were available.
[2] Per module loading and registration - Nobody was that crazy about solution [1] and we wanted each module to load only the templates needed for that particular module. So we started just listing them as "text!something.tmpl" requirements and then doing a registration of that particular template as the first line within the module that had that as a requirement. In our case, we use Handlebars as the template engine together with ICanHandlebarz (similar to ICanHaz for Mustache). So I have a call to ich.addTemplate("something", something); up at the beginning of the module code.
In a few cases, multiple modules used the same templates so I had to test to see if the template was already registered before doing the registration.
I hope one of those would help you with your problem.

Categories