잊지 않겠습니다.

'data binding'에 해당되는 글 2건

  1. 2016.09.23 Data Binding
  2. 2010.01.11 ASP .NET MVC DataBinding

Data Binding

angularjs2 2016. 9. 23. 00:26

angular2는 angular1과 다르게 한개의 Page가 여러개의 Component로 이루어집니다. 그리고 그 Component간의 데이터 전달은 Input/Output을 통해서 이루어집니다. 예전 ng-model이 이제 단방향으로 나뉘어져있다고 생각하면 쉽습니다. (ngModel과 같이 양방향 역시 존재합니다.)

기존 angular1에서의 directive에 데이터를 넣을때를 생각해보시면 쉽습니다. directive를 하나 선언하게 되면 그에 대한 scope의 범위를 다음과 같이 선언하게 됩니다.

scope: { ngModel: '=' }

위와 같이 선언된 ngModel은 html상에서 다음과 같이 사용되어질 수 있습니다.

<app-directive ng-model="models.data"></app-directive>

angular2에서는 Input과 Output을 명확하게 구분합니다. 이 부분이 어찌보면 angular1과 angular2간의 가장 큰 차이라고도 볼 수 있습니다.

기존 양방향 binding의 경우 performance의 문제가 발생했었고, 이는 angular1에서의 성능향상의 가장 큰 걸림돌이 되었던 dirty-watch의 문제점이기도 했습니다. 이 부분은 react에서도 적용되어 있는것으로, javascript에서의 refrencetype의 참조가 아닌, value로서 참조를 하게 됩니다. 이 부분은 매우 중요합니다. 결국 angular1에서의 양방향 reference binding의 문제로 binding된 model은 2개의 copy 본이 만들어지고 dirty-watch 과정을 통해 copy본과의 차이점을 알아내고 그 값을 다시 view에 binding하는 과정에서 angular1은 많은 시스템 자원을 소비하고 있었지만, angular2의 경우에는 이 과정이 없어지는거지요. binding자체가 값으로 set되는것이고, 그 set된 값은 변경되기 전에는 rendering과정을 거치지 않게 됩니다.

서론이 길었습니다. 이제 angular2에서의 DataBinding을 알아보도록 하겠습니다.

Data Binding의 종류

  • interpolation : {{}}로 표현되는 binding입니다. 값을 화면에 표시하는 용도로 사용됩니다.
  • property binding: []로 표현되는 binding입니다. Component의 property값을 set할때 사용됩니다.
  • event binding: ()로 표현됩니다. Component에서 발생되는 event를 get할때 사용됩니다.
  • two-way data binding: [()]로 표현됩니다. Component에서 값을 getset을 할 수 있습니다. 이는 ngModel directive를 이용해서만 사용 가능합니다.

먼저 간단한 2개의 Component를 통해, interpolationproperty bindingevent binding을 알아보도록 하겠습니다.

import { Component, OnInit } from '@angular/core'; import { TenantService } from '../shared/services'; @Component({ selector: 'app-feature', templateUrl: './feature.component.html', styleUrls: ['./feature.component.css'] }) export class FeatureComponent implements OnInit { tenantList: any[]; constructor(private tenantService: TenantService) { } ngOnInit() { this.tenantService.listAll().then(tenants => { this.tenantList = tenants; }); } selectedTenant(event) { console.log(event); } }
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; import * as _ from 'lodash'; @Component({ selector: 'app-tenant-list', templateUrl: './tenant-list.component.html', styleUrls: ['./tenant-list.component.css'] }) export class TenantListComponent implements OnInit { @Input() tenants: any[]; @Output() select = new EventEmitter(); constructor() { } ngOnInit() { } selectTenant(tenantId: number) { const selectedTenant = _(this.tenants).find(tenant => tenant.id === tenantId); this.select.emit(selectedTenant); }; }

FeatureComponent와 TenantListComponent가 있습니다. FeatureComponent안에서 TenantListComponent가 Table로 구현되는 아주 간단한 구조입니다.

이에 따른 html은 각각 다음과 같습니다.

// feature.component.html <app-tenant-list [tenants]="tenantList" (select)="selectedTenant($event)"></app-tenant-list>
// tenant-list.component.html <table class="table table-hover"> <thead> <th>Id</th> <th>Name</th> </thead> <tbody> <tr *ngFor="let tenant of tenants" (click)="selectTenant(tenant.id)"> <td>{{tenant.id}}</td> <td>{{tenant.defaultInfo.name}}</td> </tr> </tbody> </table>

먼저 feature.component.html에서는 property binding과 event binding이 보여집니다. TenantListComponent에서 정의된 Property인 tenants가 [tenants]="tenantList"로 set을 하고 있는 것을 보실 수 있습니다.

event binding의 경우에는 다양합니다. 우리가 주로 알고 있는 web에서의 click과 같은 event들이 event binding으로 처리됩니다. 이는 tenant-list.component.html을 보면 확인이 가능합니다.

<tr *ngFor="let tenant of tenants" (click)="selectTenant(tenant.id)">

click event가 발생하게 되면 selectTenant method가 호출이 되게 됩니다. selectTenant method는 안에서 EventEmitter 객체를 통해 이벤트를 발생시킵니다. Component에서 외부로 노출되는 값은 모두 Event가 되게됩니다.

Summary

angular2는 4개의 binding type을 가지고 있습니다. interpolationevent bindingproperty bindingtwo-way binding이 있습니다. 4개의 용도는 다음과 같습니다.

  • interpolation: model의 값을 단순 display 할때 사용됩니다.
  • event bindingParent Component에서 Child Component의 값을 가지고 올때(get) 사용됩니다. - @Output과 같이 사용됩니다.
  • property bindingParent Component에서 Child Component의 값을 설정할 때(set) 사용됩니다. - @Input과 같이 사용됩니다.
  • two-way bindingComponent안에서 value와 rendering결과를 일치시킬 때, 사용됩니다. - input element와 같이 사용되는 경우가 많습니다.

Binding 부분은 angular2의 가장 핵심적인 부분입니다. 직접 예시 application을 만들어서 해보는것이 좋을 것 같습니다. 그럼 Happy Coding!

Posted by Y2K
,
Data Binding : 규약을 이용하여 데이터 Entiry를 다루는 MVC Framework의 기능.

Model Binding
: HTML form의 submit시에 응용프로그램은 key/value pair로 폼의 데이터를 담고 있는 HTTP response를 받게 된다.
이때에, Http 요청 데이터를 Action method의 매개변수 및 사용자 정의 .NET 객체와 직접적으로 mapping하기 위한 알고리즘을 제공한다.

Model Binding 시의 데이터 적용 순서
1) Form(POST 매개변수 : FormCollection)
2) RouteData
3) QueryString

사용자 정의 형식에 대한 Model Binding
: 기본적으로 DefaultModelBinder는 {parameterName.PropertyName}으로 검색을 한다.
(* 대소문자는 가리지 않는다.)

다음과 같은 View가 존재한다고 할때에, 대응되는 ActionMethod는 다음과 같다.

New Product

<%=Html.ValidationSummary() %> <%using(Html.BeginForm()) { %> Name : <%=Html.TextBox("productValue.name") %>
Price : <%=Html.TextBox("productValue.price")%>
Description : <%=Html.TextBox("productValue.description")%>
<%} %>

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult New(Product productValue)
{
    try
    {
        productValue.CheckValidation();
    }
    catch(ProductException ex)
    {
        foreach(string key in ex.Keys)
        {
            ModelState.AddModelError(key, ex[key]);
        }                
        return View();
    }

    return RedirectToAction("NewResult",
        new { product = productValue });
}

BindAttribute의 이용
Bind Attribute는 Action Method의 매개변수 이름이 아닌 다른 이름으로 Binding을 원하거나, 특정 속성들이 모델 바인딩의 대상이 되어야하는지를 엄밀하게 제어할 필요가 있을 때 사용된다.

/// 
/// 다음 ActionMethod는 productA.*, productB.* 로 prefix된 view의 id를 이용해서 
/// 값을 Binding한다.
/// 
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult New([Bind(Prefix = "productA")] Product product1, 
    [Bind(Prefix = "productB")]Product product2)
{

}
/// 
/// 다음 ActionMethod는 Name과 Price를 Binding에 포함한다.
/// 
/// 
/// 
public ActionResult RegisterMember([Bind(Include = "Name, Price")] Product product)
{

}
/// 
/// 다음 ActionMethod는 DateOfBirthDay를 Binding하지 않는다.
/// 
/// 
/// 
public ActionResult DeregisterMember([Bind(Exclude = "DateOfBirthDay")] Product product)
{

}

[Bind(Include="Name")]
public class Product
{        
    public string Name { get; set; }
    public string Price { get; set; }
    public string Description { get; set; }
}

Array, Collection, Dictionary에 대한 Model Binding
: 동일한 이름을 갖는 여러개의 Textbox를 Render하는 View의 Controller는 다음과 같이 사용될 수 있다.

<%=Html.TextBox("movies") %>
<%=Html.TextBox("movies") %>
<%=Html.TextBox("movies") %>
public ActionResult DoSomething(IList movies) { throw new NotImplementedException(); }


사용자 정의 Entry의 Group에 대해서는 다른 방법이 필요하게 되는데, DefaultModelBinder는 ActionMethod의 사용에 C#의 문법과 동일한 명명 규약을 따르기를 요구한다. 다음과 같은 ActionMethod가 존재할 때에, 사용되는 View는 다음과 같다.

public ActionResult DoSomething(IList products)
{
    foreach(Product product in products)
    {
        System.Diagnostics.Debug.WriteLine(product.Name);
    }
    throw new NotImplementedException();
}


<%using(Html.BeginForm("DoSomething", "Products")) { %>
    <%for(int i = 0 ; i < 10 ; i++) { %>
        

<%=string.Format("Product : {0}", i) %>

<%--C#에서 사용되는 배열 문법과 동일하다.(products[0].Name, products[0].Price)--%> Name : <%=Html.TextBox("products["+i.ToString()+"].Name") %>
Price : <%=Html.TextBox("products["+i.ToString()+"].Price") %>
Description : <%=Html.TextBox("products["+i.ToString()+"].Description") %>
<%} %> <%} %>

사용자 지정 Model Binder의 지정
: 특정한 데이터에 대하여 사용자 지정 Model Binder를 사용하고 싶은 경우에는 IModelBinder interface를 상속한 사용자 지정 ModelBinder를 만들어주면 된다.



Model Binder가 사용되도록 구성하기 위해서 3가지 방법중 하나를 사용할 수 있다.
1) Model에 ModelBinderAttribute의 적용
[ModelBinder(typeof(XDocumentBinder))]
public class XDocument
{
    //...
}
2) ModelBinders.Binders.Add를 이용, 전역 ModelBinder에 등록하기
ModelBinders.Binders.Add(typeof(XDocument), new XDocumentBinder());
3) 매개변수를 Binding할때, Parameter attribute를 넣어주기
public ActionResult DoSomething([ModelBinder(typeof(XDocumentBinder))] XDocument xml)
{
    //...
}

.NET MVC Framework에서 ModelBinder Select 순위
1) Binding시에 명시적으로 지정된 Binder
2) 대상 형식을 위해 ModelBinders.Binders에 등록된 Binder
3) 대상 형식에 ModelBinderAttribute를 사용하여 할당된 Binder
4) DefaultModelBinder


Posted by Y2K
,