angular2 양방향 데이터 바인딩





Angular에서 정말로 놀랄만한 기능을 꼽자면 아마도 어플리케이션과 뷰의 데이터를 상호 공유하는 양방향바인딩 기능일 것입니다.

Angular2 이후부터는  내장된 ngModel을 사용하는 방향과 별도 지시자(directive)를 사용하여 양방향 데이터 바인딩을 구현할 수 있습니다.


양방향 데이터 바인딩

양방향 데이터 바인딩은 단방향 바인딩과 달리 뷰와 컴포넌트의 상태 변화를 상호 간에 반영합니다. 양방향 바인딩을 사용하기 위한 가장 기본적인 출발은 FormsModule의 ngModel 지시자를 사용합니다.

Angular2 이후부터는  ngModel을 속성바인딩과 이벤트바인딩을 합친 형태로 제공합니다.

아래의 소스를 살펴보면


<input [(ngModel)]="username" >
Hello {{username}}!


ngModel을 사용하여 손쉽게 양방향 바인딩을 구현할 수 있으며, ngModel 빼고는 다음과 같은 방식으로 사용합니다.

<input [value]="username" (input)="username = $event.target.value" >
Hello {{username}}

각각 요소에 대해 살펴보면

  • [value]=”username” - 컴포넌트의 username 속성을 input element의 value 속성으로 바인딩 합니다. 다시 말해 컴포넌트의 값을 뷰템플릿으로 값을 전달한다고 할 수 있습니다.
  • (input)=”표현식” - input 이벤트 발생 시 다음 표현식을 실행합니다.
  • username = $event.target.value - 이벤트 발생 시 해당하는 값을 컴포넌트의 username 속성에 전달합니다.
  • $event - 이벤트 발생시 바인되는 정보를 담고 있습니다.


엘레멘트에 속성을 연결하여 엘레먼트의 상태가 바뀌었을때 해당 속성을 값을 변경하고, 속성을 바뀌었을때 엘레멘트의 속성을 따라서 변경합니다. 

위의 예제는 input 엘레먼트의 value 속성과 뷰에 해당하는 username 변수에 연결하여 양방향으로 값을 공유한다고 이해할 수 있습니다.

ngModel 이해하기

ngModel 지시자는 ngModel 프로퍼티 속성과 ngModelChange 이벤트 속성을 가지고 있으며, 아래의 소스를 보듯이  프로퍼티 바인딩과 이벤트 바인딩이 선언되었음을 확인할 수 있습니다.

[(ngModel)]="username" 은 문법적 편이를 위한 축약적 표현이며, 양방향 바인딩을 위한 [()] 기호는 ngModel에서만 사용되는 것은 아닙니다.

<input [ngModel]="username" (ngModelChange)="username = $event" >
Hello {{username}}


커스텀 양방향 데이터 바인딩 만들기

ngModel input 엘레먼트와 같이 formsModule을 사용하여 form 계열 엘레먼트에서만 사용이 가능합니다. 하지만 form계열이 아닌 엘레먼트에서 양방향 바인딩을 사용하려면 별도의 작업이 필요합니다.


다음 예제를 살펴보면

@Component({
  selector: 'custom-counter',
  template: `
    <button click="" decrement="">-</button>
    {{counter}}
    <button click="" increment="">+</button>
  `
})
export class CustomCounterComponent {

  counterValue = 0;

  get counter() {
    return this.counterValue;
  }

  set counter(value) {
    this.counterValue = value;
  }

  decrement() {
    this.counter--;
  }

  increment() {
    this.counter++'
  }
}

현재 카운터 값을 표시하는 데 사용되는 내부 카운터 속성이 있습니다. 이 속성을 양방향 데이터에 바인딩하려면 먼저 입력 속성으로 지정해야합니다. @Input () 데코레이터를 get 메소드에 추가해야 합니다.

@Component()
export class CustomCounterComponent {

  counterValue = 0;

  @Input()
  get counter() {
    return this.counterValue;
  }

  ....
}


counter를 속성으로 가지며, [] 를 사용하여 속성을 바인딩 할 수 있습니다.

<custom-counter [counter]="someValue"></custom-counter>

그 다음으로해야 할 일은 @Output () 데코레이터를 '-Change' 접미사를 가지는 EventEmitter와 연결합니다.  카운터 프로퍼티의 값이 변경 될 때마다 해당 이벤트를 내보내고 @Output () 속성을 추가하여setter 통해 값을 변경합니다.

@Component()
export class CustomCounterComponent {

  ...
  @Output() counterChange = new EventEmitter();

  set counter(val) {
    this.counterValue = val;
    this.counterChange.emit(this.counterValue);
  }
  ...

}


양방향 데이터 바인딩 구문을 사용하여 표현식을 해당 속성에 바인딩 할 수 있습니다.

<custom-counter [(counter)]="someValue"></custom-counter>
<p>counterValue = {{someValue}}</p>


완성된 소스는 다음 링크에서 확인 가능합니다.

https://plnkr.co/edit/RtrRej?p=info


결론


  1. ngModel은 양방향 데이터 바인딩을 구현하기 위해 FormsModule의 일부로 제공
  2. 커스텀 양방향 바인딩을 사용하면 form 계열이 아닌 엘레먼트에서도 양방향 바인딩을 사용가능



(참고자료) https://blog.thoughtram.io/angular/2016/10/13/two-way-data-binding-in-angular-2.html


댓글

주간 인기글

[NCP] Cloud DB구성

[Spring Boot] JPA + Pageable 을 이용한 페이징 처리

[정보] 인스타그램은 당신의 소리를 '듣고' 있을 수도 있습니다

[Android] Parcelable 에 대한 쉬운 이해

[ubuntu] 신규 계정에 sudo 권한 추가하기