ProAngularJS Ch17. 고급 디렉티브 기능

* 실행결과 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.js

  

    

This is the panel

angular.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>

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">

  
NamePrice
{{ item.name }}{{ item.price | currency }}
Change
</body> </html>

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">

  
NameQuantity
Total:{{ totalValue }}
</body> </html>

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>
  
    
Yes No Not Sure
You need to be sure
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">
Value: Yes No Not Sure Huh?
</div> <form name="myForm" novalidate>
</form> </body> </html>

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중

%d 블로거가 이것을 좋아합니다: