제2의 비엔지니어 인생관을 꿈꾸며

Posted
Filed under jQuery
# 이벤트 호출로 $scope 간의 데이터 전달관련 포스팅을 추가로 해봤다.
지난 #1편 의 포스팅은 단순히 메소드의 사용법에 대해 알아봤다면, 이번에는 각 스코프 간의 연결을 을 통해 모든관계를 정확히 이해하고 가자.
 부모 - 자식 ,  자식 - 자식 ,  부모 - 자식의 자식  ,  자식 - 자식의자식  관례를 이해할 수 있다.

(부모 - 자식 관계는, 사실 자식 - 자식의 자식의 관계와 같다 자식의 자식의 부모는 자식 이므로 .. @.@ 예제를 보자)

<!DOCTYPE html>
<html>
<head>
    <!-- https://cdnjs.com/libraries/angular.js/ -->
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-cookies.min.js"></script>    
</head>    
<body ng-app="myApp">

          <div ng-controller="NParent">

                   <div> 부모 #0 : <span ng-bind="name"></span>
                    <div ng-bind="parentname"></div>
                    <button ng-click="fnSetValue()">값 설정</button>
                    </div>

                     <div ng-controller="NChild1">
                        자식 #1 : <span ng-bind="name"></span>
                                  / 자식 #1 에 자식 #0 :
                                  <span ng-controller="NChild11">
                                        <span ng-bind="name"></span>
                                         <!--  NChild11 에는 fnWhoami() 함수가 없어 부모인 NChild1 로 찾아가서 호출한다.
                                                만약 NChild1 에도 없으면  최상위 부모인 NParent 를 찾아간다 -->
                                        <button ng-click="fnWhoami()">나는 누구?</button>
                                  </span>
                     </div>
                     <div ng-controller="NChild2">
                          자식 #2 : <span ng-bind="name"></span>          
                          <button ng-click="fnNC2SetValue()">내 이름 {{name}} 으로 모든 값 설정</button>
                     </div>
          
        </div>
  
        <script type="text/javascript">
                var m = angular.module("myApp" , []);    

               // DOM 구조상 부모 $scope 
                m.controller("NParent" , function($scope)
                {        
                    // 자식의 모든 name 변수에 영향을 받음
                    $scope.name = "pluginn"; 

                    // 자식의 모든 
parentname 변수에 영향을 받으나, 본인만 있으므로 본인만 받음
                    $scope.parentname = "pluginn parent"; 
                    $scope.fnSetValue = function()
                    {     
                       // 자식 $scope 의 setValue $on 이벤트 함수 호출               
                        $scope.$broadcast("setValue" , "");
                    }

                    // 자식 $scope 로 부터 호출 당해질 이벤트 함수 등록
                    $scope.$on("brSetValue" , function(e,d)
                   {
                       // 자식 $scope에 $on 으로 등록된 setValue 이벤트 함수 모두 콜
                       $scope.$broadcast("setValue" , d);
                    });
                });
                
                m.controller("NChild1" , function($scope)
                {
                   //  부모로부터  불려질 이벤트 함수 setValue 등록
                  $scope.$on("setValue" , function(e , d)
                  {
                        if (d == "") d = " ++  자식1_이름 SET ++ ";
                        $scope.name = d;                        
                  });

                  $scope.fnWhoami = function()
                  {
                           alert("NChild1");
                   }
                });
                m.controller("NChild11" , function($scope)
                {
                    //  부모로부터  불려질 이벤트 함수 setValue 등록
                    $scope.$on("setValue" , function(e,d)
                    {
                        if (d == "") d = " ++ 자식1의 자식1이름 SET ++";
                        $scope.name = d;                      
                    });
                });
                
                m.controller("NChild2" , function($scope)
                {
                    //  부모로부터  불려질 이벤트 함수 setValue 등록
                   $scope.$on("setValue" , function (e ,d)
                   {
                      
                        if (d == "") d = " ++ 자식2_이름 SET ++";                  
                        $scope.name = d; 
                    });

                    $scope.fnNC2SetValue = function()
                    {
                       // 본인 한테 
parentname 가 없기때문에,  부모한테 있는 parentname 값을 호출함,
                       alert($scope.parentname); // 부모의 parentname

                       //  parentname에 값을 셋팅 하면 (부모 자원인 읽기만 가능, 변경음 못함)
                       // 부모의 parentname 가 아닌, 본인스코프에 없었기때문에 새로은 parentname 생성
                       $scope.parentname = "xxx"; 

                       // 부모 $scope 로가서 값을 호출해보면 xxx 가  아님을 알 수 있다.
                       /// 결국 함수, 변수는 본인 $scope없을경우 부모 $scope 로 타고가면서 찾아감

                       alert($scope.parentname); // NChild2의 parentname

                       // $emit 로 부모의 brSetValue 이벤트 함수 호출 , 값으로는 name 전달
                       $scope.$emit("brSetValue" , $scope.name);
                    }
             
                });
        </script>
</body>
</html>
2018/04/05 16:39 2018/04/05 16:39
Posted
Filed under jQuery

ng-bind 는 angular 의 변수 또는 model 과 연결되는 M-V 의 연결역할을 하는 Directive 이다. 또는, 인터폴레션으로 {{ }} 작성해도 같은 효과를 본다. 근데 공부를 하다보니 , 네임설정에 있어. period 가 들어간 네임이 작동하거나 , 안하는 경우가 있어, 정리해 두기로 했다.

# ng-bind 네임설정  #1  "일반적인 영문 / 영+숫자" 
<body ng-app="myApp">
        <div ng-controller="myCtrl">
            <div>name : <span ng-bind="name"></span></div>            
            <div>name : <span ng-bind="name12"></span></div>            
        </div>
          
        <script type="text/javascript">
                var m = angular.module("myApp" , []);    
                m.controller("myCtrl" , function($scope)
                {                    
                    $scope.name = "pluginn";     // 정상 작동
                    $scope.name12 = "pluginn12"  // 정상 작동
                });
        </script>
</body>
단,네임설정에있어, 숫자만으로 이루어진 명칭 또는 영문+숫자 혼용이 아닌 숫자+영문 인 경우 , 프로그램의 기초와 같은 개념을 갖고있어, 작동되지 않는다. (예, 1111,2342 , 11name  ,11price  모두 오류)


# ng-bind 네임설정  #2   "period 를 붙인 네임 name.nickname "
<body ng-app="myApp">
        <div ng-controller="myCtrl">      
            <div>name.nickname : <span ng-bind="name.nickname"></span></div>            
        </div>
          
        <script type="text/javascript">
                var m = angular.module("myApp" , []);    
                m.controller("myCtrl" , function($scope)
                {                    
                    $scope.name.nickname = "plug~ plug~"; // 오류발생 작동하지 않음
                });
        </script>
</body>
으잉 안된다 이상하네, 아래를 보자.

# ng-bind 네임설정  #3   "period 를 붙인 네임 name.nickname "  by ng-model
<body ng-app="myApp">
        <div ng-controller="myCtrl">      
           <input  type="text" ng-model="name.nickname"/>
            <div>name.nickname:<span ng-bind="name.nickname"></span></div><!-- 정상작동 -->
            <div>{{name.nickname}}</div> <!-- 정상작동(인터폴레이션)-->
        </div>
          
        <script type="text/javascript">
                var m = angular.module("myApp" , []);    
                m.controller("myCtrl" , function($scope)
                {                    
                   //  angluar 가 제어할수있도록, 컨트롤 등록만 해준다
                });
        </script>
</body>
음, ng-model 로 설정된 이름이는 객체처럼 접근이되는 네임이 가능하다. 그럼 예제를 하나더 들어보자


# ng-bind 네임설정  #3   "period 를 붙인 네임 name.nickname "  by Array
<body ng-app="myApp">
        <div ng-controller="myCtrl">     
            <div>name.nickname:<span ng-bind="name.nickname"></span></div> <!-- 정상작동-->
            <div>{{name.nickname}}</div> <!-- 정상작동(인터폴레이션)-->
        </div>
        <script type="text/javascript">
                var m = angular.module("myApp" , []); 

                m.controller("myCtrl" , function($scope)
                { 
                          var name = { nickname : "pluginn" };
                          $scope.name = name;               
                });
        </script>
</body>
작동된다. 결국 period(.) 의 의미는 프로그래밍에서와 마찬가지로 객체의 속성접근으로 봐야한다.
네임에는 . 를 사용하지 말자 , 

ng-Model (예, ng-model="name.first") 또는 배열과같은 객체명의 속성 성격의 period 네이밍은 가능하나, 변수명  자체로서의 period 사용은 자제하기로 하자. 일반적인 프로그래밍에서이 사용방법과 딱히 다를것이
없다.
2018/04/05 13:21 2018/04/05 13:21
Posted
Filed under jQuery
# ng-if
 ng-if  구문안의 조건이 맞으면 본인을 show 틀리면 hide
<body ng-app="myApp">
                <input type="text" ng-model="sbtxt" value="">
                <div ng-if="sbtxt == 'red' ">빨강색</div>
          
        </div>
       <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
        <script type="text/javascript">
                var myApp = angular.module('myApp', []);
        </script>
</body>


# ng-switch on ~ ng-switch-when 문

 ng-switch on 에 연결된 ng-model 의 value 에 따라 ng-switch-when 조건에 설정된
 블럭들이 show/hide 됨 , 아래 예제
<body ng-app="myApp">

                <select id="sb" ng-model="sbcolor">
                    <option value="">선택</option>
                    <option value="1">red</option>
                    <option value="2">green</option>
                    <option value="3">blue</option>                                        
                </select>

                <div ng-switch  id="aa" on="sbcolor">                 
                  <div ng-switch-when="1" class="box red"></div>
                  <div ng-switch-when="2" class="box green"></div>
                  <div ng-switch-when="3" class="box blue"></div>
                  <div ng-switch-default class="box black"></div>
                </div>
          
        </div>
       <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
        <script type="text/javascript">

                var myApp = angular.module('myApp', []);
        </script>
</body>


# ng-show , ng-hide
ng-show 구문 안의 조건이 맞으면 자신을 show 틀리면 hide 한다.
ng-hide   구문안의 조건이 맞으면 자신을 hide 하고 틀리면 show 한다.
<body ng-app="myApp">

                <input type="text" ng-model="sbtxt" value="">

                <div ng-show="sbtxt=='red' ">빨강색 O</div> <!-- 참이면 보임  -->
                <div ng-hide="sbtxt=='red' ">  빨강색 X</div>  <!-- 참이면 숨김 -->
          
        </div>
       <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
        <script type="text/javascript">
                var myApp = angular.module('myApp', []);
        </script>
</body>


# ng-class
ng-class 구문안에 조건에 만족하면 선언한 클래스가 블럭에 적용된다.
ng-class = "{클래스명 : 조건 , 클래스명 : 조건 , 클래스명 : 조건.......}"
<style type="text/css">
    .red {color:#F00}
    .green {color:#0F0}
    .blue {color:#00F}
</style>
<body ng-app="myApp">
       <input type="text" ng-model="sbtxt" value="">
       <div ng-class="{red : sbtxt == 'red' , blue : sbtxt == 'blue' }">안녕하세요</div>          
        </div>
       <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
        <script type="text/javascript">
                var myApp = angular.module('myApp', []);
        </script>
</body>
2018/04/04 14:03 2018/04/04 14:03
Posted
Filed under jQuery

모듈로 다루어지는 angular 에서는 각 콘트롤별로 $scope 라는 일종에 개체를 가지게 되는데, 개인적으로는  this 와 꽤
비슷한 느낌이다. (물론 개념적으로는 다르다)

각각의 controller 들은 각각의 $scope 와 연결되어 MVC 를 오가며, 데이터를 전달하고 연결한다. 하지만 각각의 $scope 는 다른 $scope 즉 컨트롤들의 영역을 공유할 수 없다. 간혹 각각 다른 $scope 간의 데이터를 주고 받아야할때가 있는데,  그리도 지금 소개할 ,  $emit , $on , $broadcast 를 활용하는 방법이다.
(단, DOM 구조상 부모 $scope 인 경우,  자식 $scope 의 바인드 변수 접근이 가능함)

간단하게 보자면,
- 같은 노드위치의 $scope 끼리는 $scope 로 데이터를 전달할 수 없다.
- 자식 $scope 에서 부모 $scope 의 함수 및 변수를 호출 할수 있다, (단, 변경할 수 는 없다.)

자식 $scope에서 $emit  메소드를 통해 부모의 이벤트 함수를 호출하여 값을 전달하고, 값을 받은 부모는 다른 자식 $scope의 이벤트 함수를 호출해서 값을 전달해준다.

설명보다는 예제를 통한 설명이 쉬울꺼같아 예제의 주석으로 설명을 대체한다 (나중에 개인적으로 꺼내봤을대도 쉽다 --)

 <!DOCTYPE html>
<html>
<head>
<!-- https://cdnjs.com/libraries/angular.js/ -->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-cookies.min.js"></script>
</head>
<body ng-app="scopeTest">
          <div ng-controller="ncParent">
                    <div ng-controller="ncChild1">
                              ncChild1-var1 : <span ng-bind="var1"></span> /
                              ncChild1-varA : <span ng-bind="varA"></span>
                    </div>
                    <div ng-controller="ncChild2">
                              ncChild2-var1 : <span ng-bind="var1"></span> /
                              ncChild2-varB : <span ng-bind="varB"></span>
                    </div>
                    <div ng-controller="ncChild3">
                              ncChild3-var1 : <span ng-bind="var1"></span> /
                              ncChild3-varC : <span ng-bind="varC"></span>
                    </div>

                    <button ng-click="fnBroadCast()">자식에게전달</button>
</div>
<!--
          $on("이벤트명" , function(event, data) {})
          $emit() - 특정 범위를 이벤트로 부모에게 전달. - ($rootScope가 아닌 DOM 구조의 부모 이벤트 호출)
          $broadcast() - 특정 범위를 모든 자식에게 전달.- 부모(DOM) 하위 자식의 이벤트 함수 호출
          $emit("호출이벤트명" , 전달할데이터) 
          $broadcast("호출할 자식의 이벤트명" , 전달할데이터) 
          $on , $emit , $broadcase 메소드 메커니즘
          1) 자식1 본인 값을 $emit() 통해 부모에게만, 전달하고 
          2) 그 값을 받은 부모는 $broadcast 로 자식의 이벤트 함수들을 모두 호출
          부모가 $boardcase 로 호출 당하고 싶은 자식들은 $on 메소더를 구현해야놔야한다.
          1)ncChild1 에서 부모로 scope을 전달
          2)ncParent는 $on() 메소드를 사용하여 이벤트를 감지
          3)ncParent가 전달받은 값(범위)을 $broadcast() 메소드를 사용하여 자식요소로 전달

 -->
<script lang="javascript">
var app = angular.module("scopeTest" , []);
app.controller("ncChild1" , function($scope)
{
         $scope.var1 = "Pluginn";
         $scope.$emit("sendVar1" , $scope.var1); // 자신의 부모 이벤트함수(sendVar1) 호출
         $scope.$on("getVar1" , function(event ,data)
         {
                  $scope.varA = data;
         });
});
app.controller("ncChild2" , function($scope)
{
         // 부모로부터 $broadcast 될 함수
         $scope.$on("getVar1" , function(event, data) 
         {
                  $scope.varB = data;
         });
});
app.controller("ncChild3" , function($scope)
{
         // 부모로부터 $broadcast 될 함수
         $scope.$on("getVar1" , function(event , data) 
         {
                  $scope.varC = data;
         });
});
app.controller("ncParent" , function($scope)
{
         $scope.$on("sendVar1" , function(event ,data)
         {
                  // tes1, test2, test3의 parent $scope 로써 자식 $scope 의 binder 접근가능
                  // 자식의 var1 변수로 모두 접근되는것을 볼수있다.
                  $scope.var1 = data;
         });
         $scope.fnBroadCast = function()
         {
                  alert("전달");

                  // 자식 $scope 에 등록된 이벤트 함수를 호출 
                  $scope.$broadcast("getVar1", $scope.var1);   
         }
});
</script>
</body>
</html>
2018/03/27 17:09 2018/03/27 17:09
Posted
Filed under jQuery

업무상(ajax 뿐만 아니라)  클라이언트쪽의 페이지 인코딩 과 서버측 인코딩이 달라서 한글이 깨지는 경우가 많이 발생한다.
물론 요즘 대부분 utf-8로 개발을 하기때문에 흔하지 않을수도있지만 환경에따라 ,어쩔수없이 euc-kr 와 utf-8을 동시에
이용해야 하는 경우가 있다.

나의 경우는,  클라이언트 페이지가 euc-kr(완성형 한글) 이지만 내부적으로 ajax 가 utf-8로 변환하여 
서버 페이지 (euc-kr)에 전송하면서,  클라이언트서버의 인코딩 환경이 맞지 않기(같지 않기때문) 때문에 생긴 문제였다

아래는 full code 는 아니지만 핵심만 요약해서 정리하였다(code가  중요하지는 않다)

(참고로 한글이 깨지지않게 하는 방법은 사실 URL 인코딩 말고, 다른방법도 있다. 하지만  URL 인코딩을 통해 데이터를 전송하면 ContentType 이나 Mime 설정 등.. 페이지 언어 설정이 필요없다.)

<script language="javascript">

       var txt;
       txt = encodeURI("가나다라마")  - // 1차  Url 인코딩(서버 함수일경우 서버 함수로)
       txt = encodeURI("가나다라마") -  // 2차  Url 인코딩(서버 함수일경우 서버 함수로)
         
        //  서브밋 처리

</script>

[변환후]

%EA%B0%80%EB%82%98%EB%8B%A4%EB%9D%BC%EB%A7%88  // 1차
%25EA%25B0%2580%25EB%2582%2598%25EB%258B%25A4%25EB%259D%25BC%25EB%25A7%2588 // 2차

(1차에서 변환한 문자열의, % 가 2차에서 %25 로만 변경된것을 볼 수 있다.)


그럼 왜 2번 해줄까? 

이유는 간단하다.  Url 인코딩된 문자열을 보존하기 위해서이다.
만약 1회만 할 경우,   서브밋시 서버에서 자동으로 디코딩을 1회 하면서 url 인코딩된 것이 
utf-8 데이터로 노출된다
그래서 한글로 변환하게되니 깨진다.  2회 하게되면,  서버측에서 자동 1회 인코딩하더라도, 1차로 Url인코딩된게 남아있기때문에 깨지지않는다.

{{ 2회 인코딩한 데이터 서버로 전송 }}
%25EA%25B0%2580%25EB%2582%2598%25EB%258B%25A4%25EB%259D%25BC%25EB%25A7%2588

{{ 서브밋 되면서 중간에 서버가 1번째 디코딩함 }}
%25EA%25B0%2580%25EB%2582%2598%25EB%258B%25A4%25EB%259D%25BC%25EB%25A7%2588

%EA%B0%80%EB%82%98%EB%8B%A4%EB%9D%BC%EB%A7%88

{{ 서버 페이지에서  2번째  디코딩함 }}
%EA%B0%80%EB%82%98%EB%8B%A4%EB%9D%BC%EB%A7%88 

 "가나다라마"  변환완료

 DB 저장함

2018/03/14 17:06 2018/03/14 17:06