반응형

 

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';


import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

template driven 에서는 FormsModule을 사용합니다.

 

template driven에 들어가기 앞서 용어와 개념을 정리해보았습니다.

 

투 웨이 바인딩(2-way-binding) 이해하기

 

What are the difference between one way binding and two way binding?

Answer (1 of 5): A two-way binding involves an implementation of a single “watcher set” for both the model and the component, and updating either one when the other changes. Angular 1 uses this method by default using ng-Model. Watchers are created to hand

www.quora.com

 

이벤트 바인딩

<button (click) = “TheEventMethod()”>Save</button>

DOM에서 JavaScript function을 작동 시키도록 event를 알립니다.

 

속성(프로퍼티) 바인딩

<p[size] = “fontSizePx”></p>

JavaSciprt로 설정된 fontSizePx라는 변수값을 가져옵니다.

 

2-way-바인딩

<input type='text' placeholder= "Enter stock symbol" [(ngModel)] = "lastStockSymbol">

이벤트 바인딩과 속성 바인딩을 동시에 사용하는 것이 2-way-바인딩 입니다.

클릭 이벤트 function을 상징하는 ()와 속성 바인딩 []두개가 동시에 쓰인것이 보이죠?

<input type='text' placeholder= "Enter stock symbol" [value]="lastStockSymbol" (input) = "lasStockSymbol=$event.target.value">
<br>The value of lastStockSymbol is {{lastStockSymbol}}

service를 이용하여 DOM을 update함으로써, 2-way-binding을 구현할 수 있습니다.

 


#foo 로컬 레퍼런스

 

1. regist - input input태그를 이용하여 Angular에게 알리기를 실행해 봅니다..

 

input 태그에 directive를 추가합니다. ngModel :2-way-binding이 됩니다.

html directive를 추가해줍니다

<form>
  <div id="user-data">
    <div class="form-group">
      <label for="username">Username</label>
      <input 
        type="text"
        id="username" 
        class="form-control"
        ngModel
        name="username">
    </div>
  </div>
</form>

submit할 수 있도록 만들어 보겠습니다.

 

form태그 안에 submit 버튼을 만들어 type="submit"을 만들게 클릭하게 한다면, HTML의 defalut로 작동하는 call이 trigger되어 request를 보내기 때문에, form태그에 (ngSubmit)="onSubmit()"을 추가합니다.

<form (ngSubmit)="onSubmit()">...</form>

ts

onSubmit() {
  console.log("submitted!")
}

또한 form의 reference를 받으려면 #f를 추가하면 됩니다.

 

HTML

<form (ngSubmit)="onSubmit(f)" #f="ngForm">...</form>

#f 는 local reference입니다.

Angular가 자동적으로 Javascript 객체를 생성해줍니다.

 

typescript

// <form (ngSubmit)="onSubmit(f)" #f></form>
onSubmit(form: ElementRef) {
  console.log(form);
}

// <form (ngSubmit)="onSubmit(f)" #f="ngForm"></form>
onSubmit(form: NgForm) {
  console.log(form);
}

form을 보면 아래와 같이 접근할 수 있습니다.

NgForm.value={

  key: value

}

 

2-way-바인딩을 조금더 편하게 사용하기 위해 @ViewChild를 이용합니다.

import { Component, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';

export class AppComponent {
  @ViewChild('f') singupForms: NgForm;
  
  onSubmit() {
    console.log(this.singupForms);
  }
}

ViewChild는 로컬 레퍼런스와 element를 TypeScript 코드로 변경 하기에 유용하기 때문입니다.


Form State

 

form태그 안쪽에 있는 input에 다음과 같은 directive를 사용할 수 있습니다.

또한  required, eail과 같은 vaild설정을 할 수 있습니다.

 

local reference 사용하기.

 

<input 
  type="email" 
  id="email" 
  class="form-control"
  ngModel
  required
  email
  #email="ngModel">
<span class="help-block" *ngIf="!email.vaild && email.touched">Please enter for vaild</span>

email input태그를 선택 후 아무것도 입력하지 않고 벗어나면, please enter for vaild라는 문구가 나오게 됩니다.

#email="ngModel" 을 사용함으로써 local reference로 HTML에서 email을 사용할 수 있습니다.

 

이와 마찬가지로,

submit 버튼에 disabled를 추가할 수 있습니다.

<button 
  class="btn btn-primary" 
  type="submit"
  [disabled]="!f.vaild">
Submit</button>

CSS 스타일을 관리합니다.

input.ng-invaild { ... }

Angular가 class를 추가하여 form에 위와 같은 상태를 갖고 있습니다.

 


default값 설정하기! - one-way-binding

기본값을 지정할 수 있습니다. [ngModel]

 

HTML

<select 
  id="secret" 
  class="form-control"
  [ngModel]="defaultQuestion"
  name="secret">
  <option value="pet">Your first Pet?</option>
  <option value="teacher">Your first teacher?</option>
</select>

ts

export class AppComponent {

  defaultQuestion = "pet";

}

그림과 같이 pet option태그가 설정되어 있습니다.

 


2-way-바인딩

 

<div class="form-group">
  <textarea 
    name="questionAnswer" 
    rows="3"
    [(ngModel)]="answer"></textarea>
</div>
<p>Your reply: {{answer}}</p>
export class AppComponent {
  answer = '';
}

 

No-바인딩 : Angular에게 input이 동작만 전달합니다.

1-way-바인딩 : 기본값(default value)을 이용하여 값에 나타납니다.

2-way-바인딩 : 사용자 입력과 동시에 value와 화면에 나타납니다.

 


그룹핑 하기 - ngMoudelGroup

<form (ngSubmit)="onSubmit()" #f="ngForm">
  <div
    id="user-data"
    ngModelGroup="userData"
    #userData="ngModelGroup">
      <div class="form-group">
        <label for="username">Username</label>
        <input
        type="text"
        id="username"
        ngModel
      </div>
      <div class="form-group">
        <label for="email">Mail</label>
        <input
        type="email"
        id="email"
        class="form-control"
        ngModel
        name="email">
      </div>
  </div>
</form>

ngForm.value.userData 가 그룹으로 묶여 있음을 확인할 수 있습니다.


2-way-바인딩 다른 방법

 

ngForm.setValue();

this.signupForm.setValue({
  userData: {
    username: suggestedName,
    email: ''
  },
  secret: 'pet',
  questionAnswer: '',
  gender: 'male'
});

모든 값이 덮어쓰기가 됩니다.

 

ngForm.form.patchValue();

this.signupForm.form.patchValue({
  userData: {
    username: suggestedName
  }
});

한개의 값만 변경합니다.


값 빼내기

 

user = {
    username: '',
    email: '',
    secretQuestion: '',
    answer: '',
    gender: ''
  };

onSubmit() {
  this.user.username = this.signupForm.value.userData.username;
  this.user.email = this.signupForm.value.userData.email;
  this.user.secretQuestion = this.signupForm.value.secret;
  this.user.answer = this.signupForm.value.questionAnswer;
  this.user.gender = this.signupForm.value.gender;

  this.signupForm.reset();
}

위와 같이 객체를 만들어 사용합니다.

 

반응형

'프로그래밍 > Angular' 카테고리의 다른 글

Form - 복습 및 보충 내용  (0) 2019.08.14
FormHandling - Reavice  (0) 2019.07.02
Observable & Subject  (0) 2019.06.26
Router 정리  (0) 2019.06.25
Routes  (0) 2019.06.17
반응형

어씽크(asynchronous) 핸들러입니다. 솔찍히 Promise와 모가 다른지 모르겠지만... 말이죠.

 

Ajax와 같은 기존에 사용하던 기능이 있는데 생소한 Observable을 사용하려니 이만저만 힘든게 아니라는 생각이 들었습니다.

하지만 Router를 이용하면서 이미 Observable를 이용했다고 하니 외부 라이브러리를 사용할 필요가 없다는 것을 알았습니다.

 

Route.params.subscribe()에서 params가 Observable이였습니다.

 

다음은 Observable을 사용하는 간단한 예제입니다.

import { Component, OnDestroy, OnInit } from '@angular/core';

import { interval, Subscription } from 'rxjs';

export class HomeComponent implements OnInit, OnDestroy {

  private firstObsSubscription: Subscription;

  ngOnInit() {
    this.firstObsSubscription = interval(1000).subscribe(count => {
      console.log(count);
    });
  }

  ngOnDestroy(): void {
    this.firstObsSubscription.unsubscribe();
  }

}

직접 unsubscribe해야 합니다. route.params에서는 Angular가 뒤에서 unsubscribe까지 지원해 주었습니다.

 

data(customedName), error, complete를 이용하기 예제

const customIntervalObservable = Observable.create(observer => {
  let count = 0;
  setInterval(() => {
    observer.next(count);
    if (count == 5) {
      observer.complete();
    }
    if (count > 3) {
      observer.error(new Error('Count is greater 3!'));
    }
  count++;
  }, 1000);
      
this.firstObsSubscription = customIntervalObservable.subscribe(data => {
    console.log(data);
  }, error => {
    console.log(error);
    alert(error.message);
  }, () => {
    console.log('Completed!');
  });
}

error혹은 complete을 만나면 event emit은 끝납니다.

 

Operators를 이용해서 filter, map등 이용할 수 있습니다.

import { map, filter } from 'rxjs/operators';

customIntervalObservable.pipe(filter(data => {
      return data > 0;
    }), map((data: number) => {
      return 'Round: ' + (data+1);
    })).subscribe...

Subject는 service를 이용하여 컴포넌트간 통신을 할 때 유용합니다.

 

Observable대신, Subject로 할 수 있습니다. 두 개의 차이는 Passvie와 Active로 나눌 수 있습니다.

Subject를 사용하면 수동으로 next()를 사용해야 하는데,


다만 @Output를 사용할 때, EventEmitter대신 Subject를 사용시 주의해야 합니다.

 

Useful Resources:
Official Docs: https://rxjs-dev.firebaseapp.com/
RxJS Series: https://academind.com/learn/javascript/understanding-rxjs/
Updating to RxJS 6: https://academind.com/learn/javascript/rxjs-6-what-changed/

 

RxJS 6 - What Changed?

RxJS 6 changes everything! Or does it? It certainly breaks your imports and operator usage. Time for some (quick!) fixes!

academind.com

 

자료 출처 : https://www.udemy.com/share/1000imAkEeeVhSQ34=/

반응형

'프로그래밍 > Angular' 카테고리의 다른 글

FormHandling - Reavice  (0) 2019.07.02
Handling Form - Template Driven  (0) 2019.07.02
Router 정리  (0) 2019.06.25
Routes  (0) 2019.06.17
Providers - Hierarchical Injector  (0) 2019.06.16
반응형

Router를 정리하고 직접 구현에 적용해 보았습니다.

<ts.file>

 

app 모듈 등록시 '' path를 'localhost:4200'일 때만 적용하려면,

const appRoutes: Routes = 
[ 
  { path: '', component: HomeComponent},
  { path: 'users', component: UsersComponent},
  { path: 'servers', component: ServersComponent}, 
];

path: '' 일경우, 아래와 같이 전체 경로 주소임을 나타내는 full을 추가해 준다.

{path: '', redirectTo: '/recipes', pathMatch: 'full'},

동적경로를 추가 하고 싶을 때, :foo 와 같이 콜론(:)을 앞에 붙여 추가한다.

{path: ':id'}

Route.navigate() 매쏘드 사용법 - from[localhost:4200/recipes] to[localhost:4200/recipes/0/edit]

id: number;

constructor(private router: Router, 
			private route: ActivatedRoute) { }

this.router.navigate(["/recipes", this.id, "edit"]) // 절대경로
this.router.navigate([this,id, "edit"], {relativeTo: this.route}) // 상대경로
this.router.navigate(["../", this,id, "edit"], {relativeTo: this.route}) // 한단계 이전 위치에서 상대경로 이동

 

<HTML>

 

routerLinkActive : 선택된 Element에 active class를 추가시켜줌으로써, css효과를 추가해 준다.

routerLink : /로 시작하지 않으면, 상대 주소기 때문에, 현 위치를 기준으로 아래 주소를 써주면 된다.

(ex: localhost:4200/recipes/0 으로 이동하는 링크 [현 위치: localhost:4200/recipes]의 child)

<a
  style="cursor: pointer;"
  [routerLink]="[index]"
  routerLinkActive="active"
  class="list-group-item clearfix">
  <div class="pull-left">
    <h4 class="list-group-item-heading">{{ recipe.name }}</h4>
    <p class="list-group-item-text">{{ recipe.description }}</p>
  </div>
  <span class="pull-right">
        <img
          [src]="recipe.imagePath"
          alt="{{ recipe.name }}"
          class="img-responsive"
          style="max-height: 50px;">
      </span>
</a>

[routerLink]="[index]"는 자동적으로 localhost:4200/recipes/index로 이동하게 된다.

 

 

반응형

'프로그래밍 > Angular' 카테고리의 다른 글

Handling Form - Template Driven  (0) 2019.07.02
Observable & Subject  (0) 2019.06.26
Routes  (0) 2019.06.17
Providers - Hierarchical Injector  (0) 2019.06.16
custom attribute Directive  (0) 2019.06.09

+ Recent posts