* 실행결과 http://study.jeju.onl/transclude.html
* 실행결과 http://study.jeju.onl/compileFunction.html
* 실행결과 http://study.jeju.onl/directiveControllers.html
* 실행결과 http://study.jeju.onl/customForms.html
16장에 이어서 고급 디렉티브 구현을 위한 부분을 설명한다.
주 내용은 다음과 같다.
- 트랜스클루전 이용: { transclude: true }, ng-transclude
– 참조를 통해 문서 영역의 일부를 다른 문서에 삽입하는 것
– 임의의 콘텐츠를 감싼 래퍼 역활을 하는 디렉티브를 구현
– 관례적으로 엘리먼트 형식으로 사용토록 restrict 속성 사용
– 트랜스클루전 되는 콘텐츠는 디렉티브의 스코프가 아닌 컨트롤러의 스코프에서 생성된다 - 컴파일 함수의 사용
– 컴파일 함수가 링크 함수를 반환한다는 점이 중요
– 트랜스클루드 함수는 자식 스코프와 트랜스클루전 콘텐츠의 복제셋을 전달받는다 - 디렉티브 내 컨트롤러 활용
- 기타 디렉티브 추가
- 커스텀 폼 엘리먼트 구현
– 1) 외부 변화 처리
– 2) 내부 변화 처리
– 3) 데이터 값 포매팅
– 4) 커스텀 폼 엘리먼트의 유효성 검증
이에 대한 코드이다.
1) transclude.html
<!DOCTYPE html> <html ng-app="exampleApp"> <head> <title> Directive Scopes - ProAngularJS</title> <link href="/node_modules/bootstrap/dist/css/bootstrap.css" rel="stylesheet" /> <link href="/node_modules/bootstrap/dist/css/bootstrap-theme.css" rel="stylesheet" /> /node_modules/angular/angular.js /node_modules/angular/angular-route.jsangular.module("exampleApp", []) .directive("panel", function() { return { link: function(scope, element, attrs) { scope.dataSource = "directive"; }, restrict: 'E', // false로 셋팅하면 디렉티브에서 정의한 값으로 바인딩 된다 scope: true, template: function() { return angular.element( document.querySelector("#template")).html(); }, // 임의의 콘텐츠를 감싼 래퍼 디렉티브 구현시 사용 transclude: true }; }) .controller("defaultCtrl", function( $scope ) { // 컨트롤러에서 생성한 데이터로 바인딩 된다. $scope.dataSource = "controller"; }) </head> <body ng-controller="defaultCtrl"> <panel> The data value comes from the: {{ dataSource }} </panel> </body> </html>This is the panel
2) compileFunction.html
<!DOCTYPE html> <html ng-app="exampleApp"> <head> <title> Compile Function - ProAngularJS</title> <link href="/node_modules/bootstrap/dist/css/bootstrap.css" rel="stylesheet" /> <link href="/node_modules/bootstrap/dist/css/bootstrap-theme.css" rel="stylesheet" /> /node_modules/angular/angular.js /node_modules/angular/angular-route.js{{ item.name }} angular.module("exampleApp", []) .controller("defaultCtrl", function( $scope ) { $scope.products = [ { name: "Apples", price: 1.20, quantity: 2 }, { name: "Bananas", price: 2.42, quantity: 3 }, { name: "Pears", price: 2.02, quantity: 1 } ]; $scope.changeData = function() { $scope.products.push({ name: "Cherries", price: 4.02, quantity: 4 }); for( var i=0; i </head> <body ng-controller="defaultCtrl" class="panel panel-default"> </body> </html>Change
Name Price {{ item.name }} {{ item.price | currency }}
3) directiveControllers.html
<!DOCTYPE html> <html ng-app="exampleApp"> <head> <title> Compile Function - ProAngularJS</title> <link href="/node_modules/bootstrap/dist/css/bootstrap.css" rel="stylesheet" /> <link href="/node_modules/bootstrap/dist/css/bootstrap-theme.css" rel="stylesheet" /> /node_modules/angular/angular.js /node_modules/angular/angular-route.js{{ item.name }} Reset angular.module("exampleApp", []) .controller("defaultCtrl", function( $scope ) { $scope.products = [ { name: "Apples", price: 1.20, quantity: 2 }, { name: "Bananas", price: 2.42, quantity: 3 }, { name: "Pears", price: 2.02, quantity: 1 } ]; }) .directive("productItem", function() { return { template: document.querySelector("#productTemplate").outerText, // 접두어 '^'는 // 디렉티브가 적용된 부모 엘리먼트에서 다른 디렉티브를 찾는다 // ==> productTable은 productItem의 부모 노드에 있기 때문 require: "^productTable", // item.quantity에 대한 $watch 함수를 설정하여 total 계산 link: function( scope, element, attrs, ctrl) { scope.$watch("item.quantity", function() { ctrl.updateTotal(); }); } }; }) .directive("productTable", function() { return { transclude: true, scope: { // total을 저장하는 용도로 디렉티브 스코프 변수 선언 value: "=productTable", // 메인 스코프의 products 를 받기 위한 디렉티브 스코프의 변수 data: "=productData" }, controller: function($scope, $element, $attrs) { this.updateTotal = function() { var total = 0; for( var i=0; i </head> <body ng-controller="defaultCtrl" class="panel panel-default"></body> </html>
Name Quantity Total: {{ totalValue }}
4) customForms.html
<!DOCTYPE html> <html ng-app="exampleApp"> <head> <title> Custom Forms - ProAngularJS</title> <link href="/node_modules/bootstrap/dist/css/bootstrap.css" rel="stylesheet" /> <link href="/node_modules/bootstrap/dist/css/bootstrap-theme.css" rel="stylesheet" /> /node_modules/angular/angular.js /node_modules/angular/angular-route.js <style type="text/css"> *.error { color: red; font-weight: bold; } </style>angular.module("exampleApp", []) .controller("defaultCtrl", function( $scope ) { $scope.dataValue = "Not Sure"; }) .directive("triButton", function() { return { restrict: "E", replace: true, require: "ngModel", template: document.querySelector("#triTemplate").outerText, link: function( scope, element, attrs, ctrl) { var validateParser = function(value) { var valid = (value == "Yes" || value == "No"); ctrl.$setValidity("confidence", valid); return valid ? value : undefined; }; ctrl.$parsers.push(validateParser); element.on("click", function(event) { setSelected(event.target.innerText); scope.$apply( function() { // 데이터 바인딩 값을 업데이트한다 ctrl.$setViewValue( event.target.innerText); }); }); var setSelected = function( value) { var buttons = element.find("button"); buttons.removeClass("btn-primary"); for( var i=0; i </head> <body ng-controller="defaultCtrl">Yes No Not SureYou need to be sureValue: Yes No Not Sure Huh?</div> <form name="myForm" novalidate></form> </body> </html>