ProAngularJS Ch.19 전역 객체 서비스

#실행결과 http://study.jeju.onl/ch19/domApi.html

이 장에서는 전역 객체 접근, 예외 처리, 위험한 데이터 표현, 표현식 처리를 위해 AngularJS에서 제공하는 내장 서비스들을 살펴본다.
내용은 다음과 같다.

  • DOM API 전역 객체 접근
    – window 객체 접근: $window
    – document 객체 접근: $document
    – $interval 및 $timeout 활용: 함수 실행을 지연 또는 주기적 반복
    – URL 접근: $location
    – 스크롤 조정: $anchorScroll
  • 예외 처리: $exceptionHandler
    – 애플리케이션이 계속 실행되게끔 해준다. 또는 뭔가 잘못되었을 때도 사용자가 불만을 느끼지 않게끔 해주는 고급 작업에도 활용된다
    – 예외는 자바스크립트 try.. catch 블록으로 잡을 수 있으며, 이렇게 잡은 예외는 $exceptionHandler에서 처리하지 않는다
    – factory(“$exceptionHandler”, function() {})로 재정의해 메시지를 포매팅 한다
  • 위험한 데이터 처리
    – $sce: 엄격한 맥락적 이스케이핑이라는 기능으로 위험 문자열을 제거
    – $sanitize: 위험 문자열을 이스케이프된 문자열로 대체한다 (위생화)
  • 표현식 및 디렉티브 활용
    – $parse: 표현식을 변수와 맵핑하고 변환
    – $interpolate: 인라인 바인딩이 들어있는 문자열을 변환
    – $compile: 바인딩 및 디렉티브까지 HTML 수준에서 변환

$location 내용을 다룰 때, html5Mode 설정이 있는데, base 태그로
<head> … <base href=”/”> …</head> 명시를 해주지 않으면 오류가 난다.
#참고 https://docs.angularjs.org/error/$location/nobase

다음은 예제 코드이다

<!DOCTYPE html>
<html ng-app="exampleApp">
<head>
  <title>DOM API Services - 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
  /node_modules/angular/angular-sanitize.js

  <!-- HTML5Mode에서 base 태그가 없으면 nobase 오류가 뜬다
       #참조 https://docs.angularjs.org/error/$location/nobase
  -->
  <base href="/ch19/">

  

  angular.module("exampleApp", ["ngSanitize"])
    // Provider 서비스는 config()에서 설정을 변경할 수 있다
    .config( function( $locationProvider, $anchorScrollProvider) {
      // history API 기능을 사용할 수 있는지 확인하고 활성화한다
      if ( window.history && history.pushState) {
        // HTML5 모드 활성화
        $locationProvider.html5Mode(true)
      }
      // 자동 스크롤 기능을 사용하고 싶지 않으면 비활성화 시킨다
      $anchorScrollProvider.disableAutoScrolling();
    })
    /*
    // 모듈 전체에 영향을 미친다: {{, }} 문자가 먹지 않으므로 주석처리
    .config( function( $interpolateProvider) {
      // 보간문자 {{, }} 바꾸기 ==> !!, !!
      $interpolateProvider.startSymbol("!!");
      $interpolateProvider.endSymbol("!!");
    })
    */
    // 전역 객체라서 서비스 의존성 삽입을 할 필요가 없다. 
    // 참조를 위해 인자만 넣어주면 끝!
    .controller("defaultCtrl", function( $scope
          , $window, $document, $interval, $location
          , $anchorScroll, $exceptionHandler, $sanitize, $sce) {

      $scope.displayAlert = function( msg) {
        $window.alert( msg);
      };
      /*
      // button 엘리먼트는 모두 찾아서 이벤트에 반응한다
      // #참고: jqLite 버전이라, getElementById() 등의 기능이 없다(제한적)
      $document.find("button").on("click", function( event) {
        $window.alert( event.target.innerText);
      });
      */
      // #참고: javascript의 document.querySelector()를 사용해
      //        id로 엘리먼트를 찾아 동작하도록 할 수 있다
      angular.element( document.querySelector('#button2'))
        .on("click", function( event) {
          $window.alert( event.target.innerText);
      });

      $interval( function() {
        $scope.time = new Date().toTimeString();
      }, 1000);

      ///////////////////////////

      // $location에서 정의하는 이벤트: 
      // --> $locationChangeStart, $locationChangeSuccess
      $scope.$on("$locationChangeSuccess", function( event, newUrl) {
        $scope.url = newUrl;
      });

      // path, hash, search, url 등으로 location 변경시 이벤트 발생
      $scope.setUrl = function( component) {
        switch( component) {
          case "reset": 
            $location.path("");
            $location.hash("");
            $location.search("");
            break;
          case "path":
            $location.path("/cities/london");
            break;
          case "hash":
            $location.hash("north");
            break;
          case "search":
            $location.search("hotels");
            break;
          case "url":
            $location.url("/cities/london?select=hotels#north");
            break;
        }
      };

      ///////////////////////////

      $scope.itemCount = 50;
      $scope.items = [];

      for( var i=0; iThis is Dangerous data

"; $scope.$watch("dangerousData", function( newValue) { $scope.htmlData = $sanitize( newValue); $scope.trustedData = $sce.trustAsHtml( newValue); }); /////////////////////////// $scope.dataValue = "100.23"; // $interpolate 바인딩을 위해 정의해둠 $scope.totalValue = 0.0; $scope.cities = ["London", "Paris", "New York"]; }) // 오류 메시지 가독성을 높이기 위해 포매팅 하는 기능을 추가해 // AngularJS 기본 서비스인 $exceptionHandler를 오버라이드 함 .factory("$exceptionHandler", function( $log) { return function( exception, cause) { // 예외 처리를 부드럽게 넘어가기 위해 다른 기능을 정의할 수 있다 $log.error("Message: "+exception.message+" (Cause: "+cause+")"); // #출력 ==> Message: undefined (Cause: Button Click) // 왜 undefined로 나오지?? 오버드라이브 안할땐 정상작동 }; }) .directive("evalExpression1", function($parse) { // 표현식을 $parse를 통해 미리 입력해 둔다 (사용자 편의) // --> 표현식이 expressionFn이란 함수로 파싱된다 var expressionFn = $parse("total | currency"); return { scope: { amount: "=amount", tax: "=tax" }, link: function( scope, element, attrs) { scope.$watch( "amount", function( newValue) { var localData = { total: Number(newValue) + (Number(newValue) * (Number(scope.tax)/100)) } // 표현식의 정의되지 않은 변수 total을 localData와 맵핑한다 // --> 표현식 'total | currency'의 출력값 엘리먼트를 리턴 element.text( expressionFn(scope, localData)); }); } }; }) .directive("evalExpression2", function($interpolate) { // $interpolate가 $parse보다 훨씬 더 유연하다 // --> 인라인 바인딩, 문자열 처리 가능 // --> 대신 보간 함수로 스코프나 로컬데이터를 인자로 넘길 수 없음 // --> 변수가 사용되는 스코프 내에 어딘가 존재하고 있어야 한다 var interpolateFn = $interpolate( "The total is: {{ totalAmount | currency }} (including tax)"); // "The total is: !! totalAmount | currency !! (including tax)"); return { scope: { amount: "=amount", tax: "=tax", totalAmount: "=totalAmount" }, link: function( scope, element, attrs) { scope.$watch( "amount", function( newValue) { scope.totalAmount = Number(newValue) + (Number(newValue) * (Number(scope.tax)/100)); // 표현식의 정의되지 않은 변수 total을 localData와 맵핑한다 // --> 표현식 'total | currency'의 출력값 엘리먼트를 리턴 element.text( interpolateFn(scope)); }); } }; }) .directive("evalExpression3", function($compile) { return function( scope, element, attrs) { // 표현식 뿐만 아니라 ng-repeat 등과 같은 디렉티브도 지원 var content = "
  • {{ city }}
"; var listElem = angular.element(content); var compileFn = $compile( listElem); compileFn( scope); // 변환된 결과는 listElem를 append() 해야 최종 반영된다 element.append( listElem); }; }) ; </head> <body ng-controller="defaultCtrl">
Click Me1
Click Me2

Time

The time is: {{ time }}
</div>

URL

The URL is: {{ url }}

Reset Path Search Hash URL
</div> </div>

URL

This is the top.

Go to Bottom

  • {{ item }}

This is the bottom.

Go to Top
</div>

Exception Hadling

Throw Exception
</div>

엄격한 맥락적 이스케이핑(SCE)

</div>

eval Expression

Result1:
Result2:
<p>Original amount: !! dataValue !!</p> </div>
</div> </body> </html>

답글 남기기

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

WordPress.com 로고

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

Twitter 사진

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

Facebook 사진

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

Google+ photo

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

%s에 연결하는 중

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