Original: http://seanhess.github.io/2013/10/14/angularjs-directive-design.html
AngularJS directives is cool.
A very good feature of ANGULARJS is the ability to create directives, or reusable Web components. With directive you can create new HTML tags and attributes.
Directive Design principles
If you want to show a user list, you can create a directive, which directive read the $scope.users and print it out:
<user-list/>
Compared with ng-repeat, ng-repeat only deals with repetition. User-list and Ng-repeat which one can be used in many places? What if you need to display the user list in a different way in two different places?
A good directive to do only one thing
ng-repeat比
user-list好, 因为它只做一件事情
: It only repeats parts, so you can reuse him in many environments. Don't let a directive deal with everything.
A good directive is not for an application-specific
Generally speaking, if your directive can be used in a completely different application, you should have a good command of the design.
If you show bindings
The first one to learn is how Directive handles binding: Use a pair of curly braces. For example, write a directive to show a picture and a description.
The first step in directive design is to choose a good property name. I use photo-src表示image的src
, caption作为文本
. Be careful not to use names that other directive have used, such as ng-src
unless you know how they work.
The second step is to support attributes, ClassName, or element. In this example, we use the phone as an element.
<photo photo-src= "{{photo.url}}" caption= "taken on: {{photo.date}}"/>
Notice that I did not give the whole photo object to this directive. This is a good design so that the directive can work with different data structures.
Use attrs.$observe读取binding
. When the binding changes, it will call your callback.
App.directive (' Photo ', function () { return { ///specified as element using restrict: ' E ', //using the following HTML instead of <photo > Template: ' <figure><figcaption/></figure> ', replace:true, //observation, Operation Dom link:function ($scope, Element, attrs) { attrs. $observe (' caption ', function (value) { Element.find ( ' Figcaption '). Text (value) }) //attribute name camel case attrs. $observe (' Photosrc ', function (value) { Element.find (' img '). attr (' src ', Value)})}} )
If your component has its own template, you can handle all of the above attrs in a isolate scope. $observe.
App.directive (' Photo ', function () { return { restrict: ' E ', templateurl: ' photo.html ', replace:true , //pass these-names from attrs to the template scope scope: { caption: ' @ ', photosrc: ' @ ' }
}})
<!--photo.html--><figure> <figcaption>{{caption} }</figcaption></figure>
How to read and write data
Some directive need to write data, such as ng-model
.
Now write a button toggle instruction. This instruction sets the toggle state according to some Boolean values above the scope, and when clicked this value changes.
Instead of using curly braces, you use an expression.
<!--here do not use curly braces no double curly braces here--><button toggle= "Preferences.showdetails" >show details</ Button>
First of all we scope:里面使用=,
are in this setting to make it possible to use Scope.toggle in our directive.
App.directive (' Toggle ', function () { return { scope: { toggle: ' = ', }, link:function ($scope, Element, Attrs) {
The next step scope.$watch
We use is to call callback when expression changes. When toggle changes, we add or remove the active class.
$scope. $watch ("Toggle", function (value) { element.toggleclass (' active ', value) })
Finally, listen for the jquery click event and update scope. We need to use $ scope.$apply 相应改变
.
Element.click (function () { $scope. $apply (function () { $scope. Toggle =! $scope. Toggle }) }) } }})
Demo
How to Expose Events
Sometimes you want a controller to respond to an event inside a directive, such as ng-click
. Create a scroll
directive that invokes a function when the user scroll an element's use.
<textarea scroll= "onscroll (offset)" >...</textarea>
Similar to the toggle button, we map the function in the scroll attribute to the scope of our instruction.
App.directive (' scroll ', function () { return { scope: { scroll: ' & ' }, link:function ($scope, Element, Attrs) {
We still usescope.$apply
Element.scroll (function () { $scope. Apply (function () { var offset = element.scrolltop () $scope. Scroll ({ Offset:offset})})})
Demo
How to include HTML content
Directive can have HTML content by default.
Write a modal
component: a pop-up window with a close button
<modal> <p>some contents</p> <p>put Whatever you want in Here</p></modal >
Modal more than one element. We wrote a template HTML, and we used a special instruction in a Div ng-transclude
to get the HTML content in the modal.
<div class= "modal" >
Note To set transclude: true
:
App.directive (' Modal ', function () { return { restrict: ' E ', templateurl: ' modal.html ', replace: True, transclude:true, }})
ANGULARJS directive design Made Easy