Divide and conquer or how to make your application structured

    As the ancient saying goes, how many people have so many styles of writing code. In today's article, I would like to reveal all the features of correctly setting up the AngularJS structure.
    As in any application, we should have an entry point, the starting point from where our application will start. For frequent, I use just the app. In this file, which would be nice to call main.js, we will write the following code:

    (function(ng) {
    	var app = ng.app('app', []);
    	// This should be your configuration like a routeProvider or etc.
    	return app;
    })(angular);
    

    Also, this module will include other modules in the future due to dependency injection.
    What a start has been made and it would not be bad to determine the structure of the application. Define specific entities of our application. Create folders: animations, controllers, factories, directives. In fact, now we will formulate the approach that is used in the Java package.
    So, each of the directories that we created should also contain its entry points, again called main.js. For example, consider the directory with controllers. In main.js we write the following code:

    (function(ng) {
    	var app = ng.app('app.controllers', []);
    	return app;
    })(angular);
    

    As you can see, this module will be responsible for the implementation of the controllers, which we will declare below. Also now we can enable this module depending on the main module, which will take the form:

    (function(ng) {
    	var app = ng.app('app', ['app.controllers']);
    	// This should be your configuration like a routeProvider or etc.
    	return app;
    })(angular);
    

    Now we will describe a couple of controllers for our application to show how we can use. There are certain conventions with the name of the controllers, namely in the camel-case style as a class. Let's create a file in the controllers directory MainCtrl.js, which will contain our controller logic. Its contents will be something like this:

    (function(ng) {
    	var app = ng.app('app.controllers.MainCtrl', []);
    	var MainCtrl = function($scope) {
    		var localScope = {
    			message: 'Message',
    			list: [1,2,3,4,5,6]
    		};
    		ng.extend($scope, localScope);
    	};
    	app.controller('MainCtrl', ['$scope', MainCtrl]);
    	return app;
    })(angular);
    

    Let's see why this approach has the right to life. As before, we announced a module that will be built in depending on the main controller module. The controller code itself is a separate function. After that, it is included as a controller and the full recording of the controller declaration is used so that it is not broken after minimization and obfuscation. As you can see, a local variable is created in our controller as localScope. Why is this done? With a small number of variables in $ scope this is not particularly noticeable, but when there are a lot of them, the code becomes a little unreadable and therefore I just took the technique of expanding the main $ scope through the angularjs extend method. As for me, this method is beautiful, concise and fairly readable. We also add our controller to the dependency of our main module for controllers.

    (function(ng) {
    	var app = ng.app('app.controllers', ['app.controllers.MainCtrl']);
    	return app;
    })(angular);
    

    On this principle, we will build other dependencies for directives, factories, and so on. As for me, this approach gives a complete understanding of your application, its structure immediately becomes visible and very easy to upgrade, adding new controllers, services, directives and more.

    In conclusion, I would like to talk a little about controllers, or rather, about the new syntax “as”
    If we do not want our variables or some functions to be observable. Then we can fully use this approach:

    (function(ng) {
    	var app = ng.app('app.controllers.MainCtrl', []);
    	var MainCtrl = function($scope, $log) {
    		var localScope = {
    			message: 'Message',
    			list: [1,2,3,4,5,6]
    		};
    		this.nonObservableVar = {
    			one: 1,
    			two: 2
    		};
    		this.logger = function(obj) {
    			$log.info(obj);
    		};
    		ng.extend($scope, localScope);
    	};
    	app.controller('MainCtrl', ['$scope', '$log', MainCtrl]);
    	return app;
    })(angular);
    

    And in our view use this code:

    {{ main.nonObservableVar.one }}
    {{ main.nonObservableVar.two }}

    What does this give us? Well, one of the advantages is that there are no angular watchers. This speeds up our application, also makes it possible to use the context of parent controllers in nested controllers, which makes it possible to build our application more flexibly. This method is very easy to use. As before, we can also mix controller variables with $ scope variables to use $ watch, $ apply, etc.

    If interested, I will continue to write about angular and how to build beautiful and structured applications on it. I plan to write an article about using angularjs with requirejs and the nice feature of requirejs packages.

    Leave your feedback in the comments.

    PS: I wrote this post so that your application can be easily maintained in the future, so that the one who will modify your application will understand what and how you have it =)

    Also popular now: