ProAngularJS Ch16. 고급 디렉티브 구현

* 실행결과1 http://study.jeju.onl/delux-directives.html
* 실행결과2 http://study.jeju.onl/directiveScopes.html

고급 디렉티브 구현 방식에 대해 설명한다.

  • 복잡한 디렉티브 정의
    – 디렉티브 적용방식 정의: restrict –> {EACM}
  • 디렉티브 템플릿 활용
    – 직접 기술: template
    – 함수를 활용: script type=”text/template”
    – 외부 템플릿 파일: templateUrl
    – 함수를 통한 외부 템플릿 파일 동적 로드: templateUrl+function()
    – 엘리먼트 대체: replace
  • 디렉티브 스코프 관리
    – 설명: 범용으로 사용하기 위해 스코프를 분리하는 방법
    – 1) 다중 컨트롤러 생성
    – 2) 자체 스코프 부여: “scope: true”
    – 3) 고립 스코프: “scope: {}”
  • 고립 스코프의 생성
    – 1) 어트리뷰트 값을 통한 바인딩: 접두어 ‘@’
    – 2) 양방향 바인딩: 접두어 ‘=’
    – 3) 함수 바인딩: 접두어 ‘&’
    – 4) 표현식 바인딩: 본문에 새 변수를 사용하고 템플릿에서 매핑

이에 대한 소스코드이다.

1) delux-directives.html

<!DOCTYPE html>
<html ng-app="exampleApp">
<head>
  <title>Delux Directives - 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.price | currency }}
angular.module("exampleApp", []) .directive("unorderedList1", function() { return { // 링크 함수: 팩토리 함수 link: function(scope, element, attrs) { // 디렉티브가 엘리먼트로 사용될 때는 listSource 참조 var data = scope[ attrs["unorderedList1"] || attrs["listSource"] ]; // 주석 형태에서는 listProperty 지정이 없으므로 직접값 대체 var propertyExpression = attrs["listProperty"] || "price | currency"; if (angular.isArray(data)) { var listElem = angular.element("
    "); // 주석형태에서는 부모에 접근하여 추가한다 if( element[0].nodeName == "#comment") { element.parent().append( listElem); } else { element.append(listElem); } for( var i=0; i") .text( scope.$eval( propertyExpression, data[i])); listElem.append( itemElement); } } }, // restrict: 디렉티브의 사용 형태를 지정한다 // E: 엘리먼트 형태, A: 어트리뷰트 형태, C: 클래스 형태, M: 주석 형태 // ** 일반적으로 'A'를 많이 사용하고, C나 M은 사용 안한다 restrict: "EACM" }; }) .directive("unorderedList2", function() { return { link: function( scope, element, attrs) { scope.data = scope[ attrs["unorderedList2"] ]; }, restrict: "A", // template: // 1) 직접 기술하거나 템플릿을 따로 분리할 수도 있다 // "
    • " // + "{{ item.price | currency }}
    " // 2) 템플릿을 함수로 분리할 수도 있고 // function() { // return angular.element( // document.querySelector("#listTemplate")).html(); // } // ** replace 속성값을 설정하면 // 디렉티브가 적용된 div 엘리먼트를 템플릿 콘텐츠가 대체한다 replace: true, templateUrl: // 3) 템플릿을 외부 파일에서 로드한다: templateUrl // "itemTemplate.html" // 4) 외부파일을 동적으로 선택하여 템플릿을 로드한다 // function( elem, attrs) { // return attrs["template"] == "table" ? // "tableTemplate.html" : "itemTemplate.html"; // } "tableTemplate.html" }; }) .controller("defaultCtrl", function($scope) { $scope.products = [ { name: "Apples", category: "Fruit", price: 1.20, expiry: 10 }, { name: "Bananas", category: "Fruit", price: 2.42, expiry: 7 }, { name: "Pears", category: "Fruit", price: 2.02, expiry: 6 }, { name: "Tuna", category: "Fish", price: 20.45, expiry: 3 }, { name: "Salmon", category: "Fish", price: 17.93, expiry: 2 }, { name: "Trout", category: "Fish", price: 12.93, expiry: 4 }, { name: "Beer", category: "Drink", price: 2.99, expiry: 365 }, { name: "Wine", category: "Drink", price: 8.99, expiry: 365 }, { name: "Whiskey", category: "Drink", price: 45.99, expiry: 365 } ]; }); </head> <body ng-controller="defaultCtrl">

    Products

    Restrict: Element Type
    Restrict: Attribute Type
    </div>
    Restrict: Class Type
    </div>
    Restrict: Comment Type
    </div>

    Products

    NamePrice
    {{ item.name }} {{ item.price | currency }}
    --> <!-- * template 속성값에 따라 다른 템플릿이 로드된다
    -->
    This is where the list will go
    </div> </div> </body> </html>

2) directiveScopes.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

  

    

Name:

City:

Country:

angular.module("exampleApp", []) .directive("scopeDemo1", function() { return { template: "
Name:
" }; }) .directive("scopeDemo2", function() { return { template: "
Name:
", // 각 디렉티브 인스턴스별로 자신의 스코프를 생성하도록 한다 // ==> 동일 디렉티브를 사용해도 서로 영향을 주지 않는다 scope: true }; }) .directive("scopeDemo3", function() { return { template: function() { return angular.element( document.querySelector("#scopeTemplate")).html(); }, //scope: true // 고립 디렉티브: {}로 설정하면 애초부터 아무런 값도 상속받지 않는다 scope: {} }; }) .controller("scopeCtrl", function( $scope ) { // 값이 정의 되어 있어서, 모든 디렉티브에서 공유한다. (** 객체 타입) $scope.data = { name: "Adam" }; // 처음에는 같은 값으로 시작하지만, 수정하면서부터 다른 버전을 갖게 된다 $scope.city = "London"; // 정의되어 있지 않은 country는 처음부터 다른 버전을 갖는다 }) .controller("scopeCtrl0", function() { // none.. }) .controller("scopeCtrl1", function() { // none.. }) .controller("scopeCtrl2", function() { // none.. }); </head> <body ng-controller="scopeCtrl"> <!-- 같은 컨트롤러 안에서는 동일 변수를 사용하기 때문에 똑같이 변경된다 -->
</div> <hr /> <!-- 하나의 디렉티브를 서로 다르게 사용하기 위한 첫번째 방법으로 각각 별도의 컨트롤러를 생성하여 적용시켰다 -->
</div> <!-- scope: true 옵션을 사용하여 각기 동작하도록 설정했다 -->
</div> <hr /> <!-- scope: true 옵션을 사용하여 각기 동작하도록 설정했다 -->
</div> </body> </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

Name:

City:

Country:

Data Value: {{ local }}

Data Value:

Name: {{ local }}, City1: {{ cityFn() }}
City2: {{ cityFn( { nameVal: local } ) }}

angular.module("exampleApp", []) .directive("scopeDemo1", function() { return { template: "
Name:
" }; }) .directive("scopeDemo2", function() { return { template: "
Name:
", // 각 디렉티브 인스턴스별로 자신의 스코프를 생성하도록 한다 // ==> 동일 디렉티브를 사용해도 서로 영향을 주지 않는다 scope: true }; }) .directive("scopeDemo3", function() { return { template: function() { return angular.element( document.querySelector("#scopeTemplate1")).html(); }, //scope: true // 고립 디렉티브: {}로 설정하면 애초부터 아무런 값도 상속받지 않는다 scope: {} }; }) .directive("scopeDemo4", function() { return { template: function() { return angular.element( document.querySelector("#scopeTemplate2")).html(); }, // 템플릿에서 정의한 객체 local 속성으로 // 어트리뷰트 nameprop를 바인딩해서 사용토록 연결 설정 // ** 접두어 '@'는 단방향 바인딩을 의미 scope: { local: "@nameprop" } }; }) .directive("scopeDemo5", function() { return { template: function() { return angular.element( document.querySelector("#scopeTemplate3")).html(); }, // 디렉티브 스코프와 컨트롤 스코프의 양방향 바인딩을 // 정의하려면 '@' 대신 '='를 사용하면 된다 scope: { local: "=nameprop" } }; }) .directive("scopeDemo6", function() { return { template: function() { return angular.element( document.querySelector("#scopeTemplate4")).html(); }, // 접두어 '&'는 지정한 어트리뷰트 city를 함수로 바인딩 scope: { local: "=nameprop", cityFn: "&city" } }; }) .controller("scopeCtrl", function( $scope ) { // 값이 정의 되어 있어서, 모든 디렉티브에서 공유한다. (** 객체 타입) $scope.data = { name: "Adam", defaultCity: "London" }; // 처음에는 같은 값으로 시작하지만, 수정하면서부터 다른 버전을 갖게 된다 $scope.city = "London"; // 정의되어 있지 않은 country는 처음부터 다른 버전을 갖는다 $scope.getCity = function( name) { return name == "Adam" ? $scope.data.defaultCity : "Unknown"; }; }) .controller("scopeCtrl0", function() { // none.. }) .controller("scopeCtrl1", function() { // none.. }) .controller("scopeCtrl2", function() { // none.. }); </head> <body ng-controller="scopeCtrl"> <!-- 같은 컨트롤러 안에서는 동일 변수를 사용하기 때문에 똑같이 변경된다 -->
</div> <hr /> <!-- 하나의 디렉티브를 서로 다르게 사용하기 위한 첫번째 방법으로 각각 별도의 컨트롤러를 생성하여 적용시켰다 -->
</div> <!-- scope: true 옵션을 사용하여 각기 동작하도록 설정했다 -->
</div> <hr /> <!-- scope: {} 옵션을 사용하여 고립 스코프 방식으로 동작하도록 설정 -->
</div> <!-- scope: {local:'@속성명'} 을 사용하여 바인딩 동작하도록 설정 ** ng-model은 양방향, nameprop는 단방향 -->
Direct Binding:
</div> <hr />
Direct Binding:
</div>
Direct Binding:
</div> </body> </html>

답글 남기기

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

WordPress.com 로고

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

Twitter 사진

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

Facebook 사진

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

Google+ photo

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

%s에 연결하는 중

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