transclude usage in Angularjs _angularjs

Source: Internet
Author: User

The examples in this article describe the transclude usage in Angularjs. Share to everyone for your reference, specific as follows:

Transclude-in the angular instructions, you will see that there is a configuration attribute, this word in the English dictionary can not query the real meaning, so in English to mark it. If you use angular in depth, you spend a great part of your time creating custom directives, so it's inevitable to get a deeper understanding of transclude. Simply put, transclude mainly completes the following tasks, taking out the contents of the custom directive (that is, the child elements written in the instruction), parsing it in the correct scope, and then putting it back in the position marked in the instruction template (usually the place where the ng-transclude is marked), Although the use of built-in ngtransclude is simple enough for basic transclude operations, there are still a lot of questions about the transclude explanation in the documentation, such as:

In the compile function received a parameter called transclude what is it? What's the use?

There is also a service in the controller called $transclude that can be injected through dependency, what is this?

What does the isolation scope have to do with transclude?

Transclude action for a property

And then we'll explain each:

The basic transclude

Let's go through a basic transclude example and we're going to create a command called Buttonbar that users can use to add a set of button to the page, which arranges the placement of different button positions. The following example CSS style is using the bootstrap framework.

See examples in fiddle: http://jsfiddle.net/ospatil/A969Z/157/

<div ng-controller= "Parentcontroller" >
  <button-bar>
    <button class= "PRIMARY" Onprimary1click () ">{{primary1Label}}</button>
    <button class=" PRIMARY ">primary2</button >
  </button-bar>
</div>

Js:

 var TestApp = angular.module (' TestApp ', []); Testapp.controller (' Parentcontroller ', [' $
  Scope ', ' $window ', function ($scope, $window) {console.log (' parentcontroller Scope id = ', $scope. $id);
  $scope. Primary1label = ' Prime1 ';
  $scope. Onprimary1click = function () {$window. Alert (' Primary1 clicked ');
};
}]);
      Testapp.directive (' primary ', function () {return {restrict: ' C ', link:function (scope, element, Attrs) {
    Element.addclass (' btn btn-primary ');
}
  }
}); Testapp.directive (' Buttonbar ', function () {return {restrict: ' EA ', Template: ' <div class= ' span4 OK clearf 
IX "><div class=" pull-right "ng-transclude></div></div> ', Replace:true, transclude:true};"

}); 

Let's look at the HTML tag first, and the buttonbar instruction wraps a few button elements. The button element is also linked to the primary instruction based on class, do not care too much about the function of the primary command it just adds some CSS style to the button element. Now let's look at the Buttonbar directive, which provides a transclude:true attribute and uses ng-transclude instructions in its template. During the run, angular gets the contents of the custom directive, and then puts the result into the Ng-transclude div on the link in the template.

Transclude to multiple locations

Now we're going to enhance the function of our Buttonbar command, we've added two buttons, primary and secondary, where the primary button is row to the right, and the secondary is the left. So to do this, it must be able to take out the contents of the instructions and add them to the different Div, one for the primary button and one for the secondary button.

In this way, the default mechanism has not met our requirements, so we have another way:

Set Transclude to True

Manually move the button element to the appropriate Div

Finally, the original element used to transclude the operation is removed from the compilation or link function of the instruction

This approach is to first insert all the content into the elements of the ng-transclude tag, and then in the link function to find the elements of the inserted elements, and then put it back to the other parts of the element, and finally delete the original staging content elements.

See examples in fiddle: http://jsfiddle.net/ospatil/A969Z/158/

<div ng-controller= "Parentcontroller" >
  <button-bar>
    <button class= "PRIMARY" Onprimary1click () ">{{primary1Label}}</button>
    <button class=" PRIMARY ">primary2</button >
    <button class= "secondary" >Secondary1</button>
  </button-bar>
</div>

Js:

var TestApp = angular.module (' TestApp ', []); Testapp.controller (' Parentcontroller ', [' $scope ', ' $window ', function ($scope, $window) {$scope. Primary1label = '
  Prime1 ';
  $scope. Onprimary1click = function () {$window. Alert (' Primary 1 clicked ');
}
}]);
      Testapp.directive (' primary ', function () {return {restrict: ' C ', link:function (scope, element, Attrs) {
    Element.addclass (' btn btn-primary ');
}
  }
});
      Testapp.directive (' secondary ', function () {return {restrict: ' C ', link:function (scope, element, Attrs) {
    Element.addclass (' btn ');
}
  }
}); Testapp.directive (' Buttonbar ', function () {return {restrict: ' EA ', Template: ' <div class= ' span4 OK clearf IX "><div class=" Primary-block pull-right "></div><div class=" Secondary-block "></div>  <div class= "transcluded" ng-transclude></div></div> ', replace:true, transclude:true, Link: function (scope, element, Attrs) {var primaryblock = Element.find (' Div.primary-block ');
      var secondaryblock = element.find (' Div.secondary-block ');
      var transcludedblock = element.find (' div.transcluded ');
      var transcludedbuttons = Transcludedblock.children (). Filter (': Button '); Angular.foreach (transcludedbuttons, function (elem) {if (Angular.element (elem). Hasclass (' primary ')) {PR
        Imaryblock.append (Elem);
        else if (angular.element (elem). Hasclass (' secondary ')) {secondaryblock.append (elem);
      }
      });
    Transcludedblock.remove ();
}
  };

 });

Although this approach achieves our purpose, it is not very efficient to allow the default transclude operation and then manually remove it from the DOM element. So we have the transclude parameter in the Compile function and the $transclude service in the controller

Transclude in the parameters of a compilation function

The developer's Guide gives us the following form of the compiler function in the directive:

function compile (telement, Tattrs, transclude) {...}

One explanation for the third parameter transclude is:

Transclude-a transclude linking Function:function (scope, CLONELINKINGFN).

OK, now we're going to use this function to implement the functionality we just talked about, so we don't have to hold the content and then insert it somewhere else.

See examples in fiddle: http://jsfiddle.net/ospatil/A969Z/161/

<div ng-controller= "Parentcontroller" >
  <button-bar>
    <button class= "PRIMARY" Onprimary1click () ">{{primary1Label}}</button>
    <button class=" PRIMARY ">primary2</button >
    <button class= "secondary" >Secondary1</button>
  </button-bar>
</div>

Js:

var TestApp = angular.module (' TestApp ', []); Testapp.controller (' Parentcontroller ', [' $scope ', ' $window ', function ($scope, $window) {$scope. Primary1label = '
  Prime1 ';
  $scope. Onprimary1click = function () {$window. Alert (' Primary 1 clicked ');
}
}]);
      Testapp.directive (' primary ', function () {return {restrict: ' C ', link:function (scope, element, Attrs) {
    Element.addclass (' btn btn-primary ');
}
  }
});
      Testapp.directive (' secondary ', function () {return {restrict: ' C ', link:function (scope, element, Attrs) {
    Element.addclass (' btn ');
}
  }
}); Testapp.directive (' Buttonbar ', function () {return {restrict: ' EA ', Template: ' <div class= ' span4 OK clearf IX "><div class=" Primary-block pull-right "></div><div class=" Secondary-block "></div> </div> ', Replace:true, Transclude:true, Compile:function (Elem, Attrs, Transcludefn) {return fu Nction (scope, element, Attrs) {transcludeFn (scope, function (clone) {var primaryblock = elem.find (' Div.primary-block ');
          var secondaryblock = elem.find (' Div.secondary-block ');
          var transcludedbuttons = clone.filter (': Button ');
              Angular.foreach (transcludedbuttons, function (e) {if (Angular.element (e). Hasclass (' primary ')) {
            Primaryblock.append (e);
            else if (Angular.element (e). Hasclass (' secondary ')) {secondaryblock.append (e);
        }
          });
      });
    };
}
  };

 });

Note that the TRANSCLUDEFN function requires a usable scope as the first parameter, but there is no scope available in the compilation function, so it is necessary to execute the TRANSCLUDEFN in the link function. This approach actually operates both compiled DOM elements and template elements in the link function (mainly because the contents of the directive are stored in the Transcludefn function).

$transclude services that can be injected into the controller

This explains the $transclude service in the Developer's Guide:

$transclude-A transclude linking function pre-bound to the correct transclusion scope:function (CLONELINKINGFN).

See how to use in our example:

See examples in fiddle: http://jsfiddle.net/ospatil/A969Z/162/

<div ng-controller= "Parentcontroller" >
  <button-bar>
    <button class= "PRIMARY" Onprimary1click () ">{{primary1Label}}</button>
    <button class=" PRIMARY ">primary2</button >
    <button class= "secondary" >Secondary1</button>
  </button-bar>
</div>

Js:

var TestApp = angular.module (' TestApp ', []); Testapp.controller (' Parentcontroller ', [' $scope ', ' $window ', function ($scope, $window) {$scope. Onprimary1click =
  function () {alert (' Primary1 clicked ');
  };
$scope. Primary1label = "Prime1"}]);
      Testapp.directive (' primary ', function () {return {restrict: ' C ', link:function (scope, element, Attrs) {
    Element.addclass (' btn btn-primary ');
}
  }
});
      Testapp.directive (' secondary ', function () {return {restrict: ' C ', link:function (scope, element, Attrs) {
    Element.addclass (' btn ');
}
  }
}); Testapp.directive (' Buttonbar ', function () {return {restrict: ' EA ', Template: ' <div class= ' span4 OK clearf IX "><div class=" Primary-block pull-right "></div><div class=" Secondary-block "></div> </div> ', replace:true, transclude:true, scope: {}, Controller: [' $scope ', ' $element ', ' $transclude ', function ($scope, $element, $transclude) {$TRANSCLUde (function (clone) {var primaryblock = $element. Find (' Div.primary-block ');
        var secondaryblock = $element. Find (' Div.secondary-block ');
        var transcludedbuttons = clone.filter (': Button '); Angular.foreach (transcludedbuttons, function (e) {if (Angular.element (e). Hasclass (' primary ')) {prim
          Aryblock.append (e);
          else if (Angular.element (e). Hasclass (' secondary ')) {secondaryblock.append (e);
      }
        });
    });
}],
  };

 });

In the same way, the parameters in the function received in the $transclude contain the contents of the instruction element, and $element contains the compiled DOM elements, so you can manipulate both the DOM elements and the instruction content in the controller, which is similar to the implementation of the compile function above. Here are a few points to note that this controller should be the controller of the instruction, and the other is to note that in addition to the first method, the ng-transclude is not used anywhere else because it is not necessary to insert into the template.

Transclude and scope

What exactly does it mean to mention in the Developer's Guide a directive isolated scope and transclude scope are siblings? If you look carefully at the example above, you will find that the Parentcontroller controller creates a scope, and the buttonbar instruction creates an orphaned scope under Parentcontroller, and according to the angular document, Transclude also creates another scope, so the isolation scope of the directive and the transclude scope are sibling scopes based on the same parent scope.

Transclude the content into the element's properties

In fact, you can't do this, but you can do it in a flexible way.

var TestApp = angular.module (' TestApp ', [])
testapp.directive (' tag ', function () {return
 {
  restrict: ' E ', C4/>template: '  
 

There is no manipulation of the DOM element, but the text content of the element is copied to the scope property and then passed to the attribute through the scope.

Also note that the clone parameter here is the entire template element in the jquery or Angular.element package.

Todo
add comparing with Ng-include

I hope this article will help you to Angularjs program design.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.