Anuglar JS 공부 <3> - 양,단 방향 바인딩

Posted by lib oimb
2019. 2. 18. 09:48 AngularJS

 

1. 바인딩

 

AngularJS는 데이터에 대한 바인딩을 제공한다. 여기서 바인딩이랑 값의 일치를 말한다.

자바스크립트를 예로 들자면

var model = document.getElementId('model').value;

// ... model을 가지고 작업 후 

document.getElementId('model').value = model;

 

이러한 작업을 말한다.

 

2. 양방향 , 단방향

 

자 그럼 양방향 바인딩과 단방향 바인딩을 알아보자.

양방향 ,단방향 바인딩은 이름에서도 알수 있듯이 바인딩 된 값이 변경 되었을 때 이 변경 된 값이 모델에 반영이 되는가를 말한다.

 

단방향 바인딩은 처음 모델값이 뷰(view)에서 변경이 일어나도 모델의 값은 변경 되지 않는다.

양방항 바인등은 처음 모델값이 뷰(view)에서 변경이 일어나면 모델의 값은 경 되어 진다.

 

 

3. 바인딩 방법 

 

바인딩 방법으로는 3가지가 있다.

 

  1. ng-bind
  2. {{model}} , {{::model}}
  3. ng-model

 

또 이 세가지 중에서 ng-model 과 {{model}} 방식은 양방향 바인딩이며 ng-bind , {{::model}} 방식은 단방향 바인딩이다.

 

양방향 바인딩의

예 1 )

<!DOCTYPE html>

<html>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>

<body>



<div ng-app="myApp" ng-controller="myCtrl">

    Name: <input ng-model="firstname">

    <h1>{{firstname}}</h1>

</div>



<script>

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope) {

    $scope.firstname = "John";

    $scope.lastname = "Doe";    

});

</script>



<p>Change the name inside the input field, and the model data will change automatically, and therefore also the header will change its value.</p>



</body>

</html>

 

 

예2 ) 

<!DOCTYPE html>

<html>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>

<body>

<div ng-app="myApp" ng-controller="myCtrl" >

<input type='text' ng-model="asd" size="80"/><br>

<span ng-bind="asde"></span>

<button ng-click="myFunction(asd)">Click Me!</button>

<p>{{ count }}</p>

</div>

<script>

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope) {

    $scope.count = 0;

    

    $scope.myFunction = function(asd) {

        $scope.count++;

 $scope.asde=asd;

    }

});

</script> 

</body>

</html>

 

 

4. 모델값이 바인딩 되는 과정 < 심화 >

 

4번째로 이야기할 부분은 좀 심화 과정이다. 따라서 넘어가도 좋다.

 

앞서 공부에서 본 그림을 다시 한번 살펴 보자.

 

 

우리가 지금 부터 공부해보려는 과정은 View==>===>===>====>ViewModel 로 가는 과정을 한번 살펴볼것이다.

< scope >

View 와 ViewModel이 모델값에 대해 바인딩이 되면 scope라는 파이프로 이어지게 된다. 여기서 흔히 간과하는 점이 있는데 View가 변경 되면 ViewModel 값이 당연히 변경된다고 생각하는 점이다. 

 

먼저 한번 예를 들어보자

<html ng-app="myApp">

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>

<body>

<div  ng-controller="myCtrl">

<form name="loginFormArea" login-form role="form" novalidate>

  <span class="pop-up-title">로그인</span>

  <div class="input-area">

    <input type="text" name="loginId" class="required" ng-required="true" ng-model="login_form.login_id" title="아이디" placeholder="아이디" ng-minlength="6">

    <div style="color: red;" ng-if="loginFormArea.loginId.$dirty || loginFormArea.$submitted">

      <div ng-if="loginFormArea.loginId.$error.required">아이디는 반드시 입력하셔야 합니다.</div>

      <div ng-if="loginFormArea.loginId.$error.minlength">아이디는 최소 6자 입니다.</div>      

    </div>

  </div>  

</form>

<p>{{login_form.login_id}}</p>

</div>

</body>

<script>

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope) { 

});

</script>

</html>

 

앞서 본 데이터 바인딩의 예에서 form태그를 이용한 $error를 검증하는것 인데 어렵게 생각할것 없다. 그냥 input text에 값을 넣게 되면 바인딩 된값이 <p> 태그에 값에 나오게하는 예시이다. 허나 이상하게도 값이 나오지 않다가 아이디가 최소 6자를 넘겨야만 값이 나타나는것을 확인 할 수 있다.

 

왜? 그럴까?

 

앞서 공부 <2>에서 한번 짧게 넘겨 집고 간 부분이 있다.

 

The purpose of $setViewValue is to propagate the value of the input / control into the ngModel pipeline:

change in control / inoput -> setViewValue -> parsers -> validators -> set on scope (simplified). Basically, you cannot separate the scope value from the value inside the ngModelController. The goal is to always have the value in the input control reflected in the whole ngModel pipeline, up to the scope value. In our example, the input value would be disconnected from the value inside the ngModelController. So the right way is to set the scope value to the last valid value, and it will propagate down to the input value.

 

 

자 change in control / inoput -> setViewValue -> parsers -> validators -> set on scope  이 부분이 핵심이다.

 

우리는 View에서의 값 변경을 예로 들었지만 Controller에서도 이와 마찬가지이다. 

모델의 값 변경이 일어나게 되면 ngModelController$setViewValue가 호출되어지고 $setViewValue는 모델값의 '업데이트'가 아닌 오로지 '전파'의 역할만을 하게 된다.

이후 $parsers가 호출되며 이는 해당 ngModelController에 등록된 함수가 호출되어지게된다. ( 이 부분은 아직 몰라도됨) 이후 'validators'에 의해 모델값이 '유효' 한가를 판다하며 유효 할 경우에 최종적으로 scope에 값이 할당되어 '업데이트'가 일어난다.

 

즉 이러한 흐름에 의해 위의 예시에서는 validators에 의해 모델 업데이트가 차단되어진다.

 

그렇다면 어떻게 해야하나... 값을 억지로라도 변경(업데이트)시켜야만 하는데... 

 

solution은 바로 ngModelOptions 이다. 여기서 설정 할 수 있는 option의 종류는 무수히 많다. 자 그럼 다시 예를 보자

 

<html ng-app="myApp">

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>

<body>

<div  ng-controller="myCtrl">

<form name="loginFormArea" login-form role="form" novalidate>

  <span class="pop-up-title">로그인</span>

  <div class="input-area">

    <input type="text" name="loginId" class="required" ng-required="true" ng-model="login_form.login_id" title="아이디" placeholder="아이디" ng-minlength="6" ng-model-options="{ allowInvalid: true, updateOn: 'blur keyup', debounce: 0}">

    <div style="color: red;" ng-if="loginFormArea.loginId.$dirty || loginFormArea.$submitted">

      <div ng-if="loginFormArea.loginId.$error.required">아이디는 반드시 입력하셔야 합니다.</div>

      <div ng-if="loginFormArea.loginId.$error.minlength">아이디는 최소 6자 입니다.</div>      

    </div>

  </div>  

</form>

<p>{{login_form.login_id}}</p>

</div>

</body>

<script>

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope) {





});

</script>



</html>

 

이번에는 값이 바로 변경되어지는 것을 알 수 있다.  ngModel의 바인딩 원리만 안다면 option은 구글링을 하여 필요한 option을 상황에 따라 주면 된다. 추가로 디렉티브에서 ngModelOptions를 건들일 수 있는데 이는 '마이디렉티브' - 파일 업로드에서 확인하자

 

그럼 다음공부로 넘어가 보자.

이 댓글을 비밀 댓글로