📜 ⬆️ ⬇️

Angularjs guidelines for beginners. Part 1

In my opinion, directives are the main highlight of the Angularjs declarative style. However, if you open user comments in the Angularjs official documentation section on directives , you will see that the most popular one is : “Please rewrite the documentation, make it more accessible and structured. It’s hard for a novice developer on Angularjs to figure out ”(“ Please rewrite a clearer well structured documentation of directives., It is difficult to disagree with this, the documentation is still damp and in some moments it is necessary to make great efforts to understand the logic and essence of the functional. Therefore, I offer you my free retelling of this chapter in the hope that it will save time for some people, and I also count on your support and participation in the comments. So let's go!

How to write directives?


Directives in Angularjs are set together with other module configurations as follows:

angular.module('moduleName', []) .directive('directiveName', function () { /*-  */ }) .directive('anotherDirectiveName', function () { /*-  */ }); 

In this case, there are two options for their ads. Simple and more powerful long options.

Simple directive creation option


In order to write a directive that will be called when specifying HTML markup, in the simplest case, you need to set a certain function (it is called Linking Linking , but more on that later) returned by the factory:
')
 angular.module('moduleName', []) .directive('directiveName', function () { return function(scope,element,attrs){ } }); 

This function takes the following parameters:

Let's take a more detailed example. Let's write such a directive (let's call habra-habr ), which will add two lines and display inside the layout element in which it is called. At the same time, we will set one line as a controller variable ( forExampleController ), and the second line as an attribute ( habra ) in the same tag. And also reserve the opportunity to determine the name of the controller variable when calling a directive:

[ jsFiddle ]
 <div ng-app="helloHabrahabr"> <div ng-controller="forExampleController"> <input ng-model="word"> <span habra-habr="word" habra="Nehabra"></span> </div> </div> 

 function forExampleController($scope) { $scope.word="Habrahabra" } angular.module('helloHabrahabr', []) .directive('habraHabr', function() { return function($scope, element, attrs) { /* ,       word,     attrs.habraHabr*/ $scope.$watch(attrs.habraHabr,function(value){ element.text(value+attrs.habra); }); } }); 

Everything. Directive in a primitive form, we are ready. You can go to a more detailed form.

Expanded version


In its full form, the directive assignment is as follows:

 angular.module('moduleName', []) .directive('directiveName', function () { return { compile: function compile(temaplateElement, templateAttrs) { return { pre: function (scope, element, attrs) { }, post: function(scope, element, attrs) { } } }, link: function (scope, element, attrs) { }, priority: 0, terminal:false, template: '<div></div>', templateUrl: 'template.html', replace: false, transclude: false, restrict: 'A', scope: false, controller: function ($scope, $element, $attrs, $transclude, otherInjectables) { } } }); 

All these properties are rather closely connected and intertwined with each other. And in order to make it easier to figure this out, they are best viewed by certain semantic groups.

Link and Compile

The Link method is the same function that the directive factory returned in the short version. Here you need to understand that in Angularjs the compilation process is divided into two stages:



And at the same time, both in the simplest version and in the extended method, the Link method will correctly call postLink , since it is executed after the variables have already been mapped. Consider the examples.

First, I propose to rewrite an example of a simple directive in an extended manner.

[ jsFiddle ]
 angular.module('helloHabrahabr', []) .directive('habraHabr', function() { return { link:function($scope, element, attrs) { /* ,       word*/ $scope.$watch(attrs.habraHabr,function(value){ element.text(value+attrs.habra); } ); } } }); 

That is, everything really works as before. Now we can complicate the task and make our phrase not be output via direct interaction with the DOM element.text (...) , but within the interpolate directive "{{}}" :

[ jsFiddle ]
 angular.module('helloHabrahabr', []) .directive('habraHabrNotwork', function() { return { link:function($scope, element, attrs) { element.html("<div>{{"+attrs.habraHabrWork+"}}"+attrs.habra+"</div>"); } } }) .directive('habraHabrWork', function() { return { compile: function compile(templateElement, templateAttrs) { templateElement.html("<div>{{"+templateAttrs.habraHabrWork+"}}"+templateAttrs.habra+"</div>"); }, link: function (scope, element, attrs) { } } }); 

Sample updated after tamtakoe comment

In the example above, the habraHabrNotwork directive will not work correctly, since we insert the "{{}}" directive with variables in the postLink, that is, when compilation and linking have already been done. In other words, Angularjs does not even know that "{{}}" is a directive that is enforceable.

Another thing, the second directive. There everything is in its place, we insert the template "{{" + attrs.habraHabrNotwork + "+" + attrs.habra + "}}" before compiling, and it is successfully rendered.

Let us dwell on the compile method. It can return both the postLink function and an object with two parameters: pre and post. Where pre and post are the preLink and postLink methods, respectively. From the name of the methods it may seem that we are talking about methods before and after Link a. But this is not entirely true; these functions are performed before and after the Link and children directives in the DOM. For example:

[ jsFiddle ]
 <div ng-app="helloHabrahabr"> <div ng-controller="forExampleController"> <input ng-model="word"> <span habra-habr-work="word" habra="NehabraParent"> <span habra-habr-work="word" habra="NehabraChild"></span> </span> <pre>{{log}}</pre> </div> </div> 


 function forExampleController($scope) { $scope.word="Habrahabra"; $scope.log=""; } angular.module('helloHabrahabr', []) .directive('habraHabrWork', function() { return { compile: function compile(templateElement, templateAttrs) { templateElement.prepend("<div>{{"+templateAttrs.habraHabrWork+"}}"+templateAttrs.habra+"</div>"); return { pre: function ($scope, element, attrs, controller) { $scope.log+=templateAttrs.habra +' preLink \n'; }, post: function ($scope, element, attrs, controller) { $scope.log+=templateAttrs.habra +' postLink \n'; } } } } }); 


On this I propose to make a pause. If the topic is interesting, in the coming days I will try to write a sequel about scopes and patterns.

Source: https://habr.com/ru/post/179755/


All Articles