Angular 19 사용자 정의 폼 컨트롤

20676 단어 angular폼 컨트롤
수요
개발 자가 특정한 폼 컨트롤 을 필요 로 할 때 기본 으로 제공 하 는 폼 컨트롤 과 비슷 한 컨트롤 을 폼 컨트롤 로 개발 해 야 합 니 다.사용자 정의 폼 컨트롤 은 모델 과 보기 간 의 데이터 가 어떻게 상호작용 을 하 는 지 고려 해 야 합 니 다.
2 공식 문서->클릭 하여 가기
Angular 는 개발 자 에 게 ControlValueAccessor 인 터 페 이 스 를 제공 하여 개발 자 에 게 사용자 정의 폼 컨트롤 을 구축 하도록 보조 합 니 다.개발 자 는 사용자 정의 폼 컨트롤 류 에서 ControlValueAccessor 인터페이스 에서 의 방법 만 실현 하면 모델 과 보기 간 의 데이터 상호작용 을 실현 할 수 있 습 니 다.

interface ControlValueAccessor { 
 writeValue(obj: any): void
 registerOnChange(fn: any): void
 registerOnTouched(fn: any): void
 setDisabledState(isDisabled: boolean)?: void
}
2.1 writeValue

writeValue(obj: any): void
이 방법 은 사용자 정의 폼 컨트롤 에 값 을 기록 하 는 데 사 용 됩 니 다.
이 매개 변수 값(obj)은 이 사용자 정의 폼 컨트롤 을 사용 하 는 구성 요소 가 템 플 릿 폼 이나 응답 식 폼 의 데이터 바 인 딩 을 통 해 전 달 됩 니 다.
사용자 정의 폼 컨트롤 클래스 에서 이 값(obj)을 구성원 변수 에 할당 하면 됩 니 다.사용자 정의 폼 컨트롤 의 보 기 는 속성 바 인 딩 을 통 해 이 값 을 표시 합 니 다.
2.2 registerOnChange

registerOnChange(fn: any): void
사용자 정의 폼 컨트롤 의 데이터 가 변 할 때 registerOnChange 방법 이 실 행 됩 니 다.이 측은 사용자 정의 폼 컨트롤 데이터 의 변 화 를 어떻게 처리 하 는 지 에 사 용 됩 니 다.
registerOnChange 방법 으로 받 은 매개 변수(fn)는 사실 하나의 방법 으로 변 화 된 데 이 터 를 처리 하 는 것 을 책임 집 니 다.
사용자 정의 컨트롤 데이터 가 변 할 때 fn 실행 방법 을 자동 으로 호출 합 니 다.그러나 일반적인 방법 은 propagate Change 를 사용 하여 사용자 정의 방법 이 fn 을 가리 키 도록 하 는 것 입 니 다.그러면 데이터 가 변 할 때 propagate Change 를 사용 하면 변 화 된 데 이 터 를 처리 할 수 있 습 니 다.
2.3 registerOnTouched

registerOnTouched(fn: any): void
폼 컨트롤 이 터치 되 었 을 때 registerOnTouched 방법 이 실 행 됩 니 다.구체 적 인 세부 사항 은 업데이트 되 어야 합 니 다.2018-1-31 11:18:33
2.4 setDisabledState

setDisabledState(isDisabled: boolean)?: void
업데이트 대기...2018-1-31 11:19:30
3 프로 그래 밍 절차
3.1 사용자 정의 폼 컨트롤 구성 요소 만 들 기

<div>
 <h4>     :{{countNumber}}</h4>
 <br />
 <div>
 <button md-icon-button (click)="onIncrease()">
  <span>  </span>
  <md-icon>add</md-icon>
 </button>
 <span style="margin-left: 30px;"></span>
 <button md-icon-button (click)="onDecrease()">
  <span>  </span>
  <md-icon>remove</md-icon>
 </button>
 </div>
</div>
HTML

import { Component, OnInit } from '@angular/core';
import { ControlValueAccessor } from '@angular/forms';
@Component({
 selector: 'app-counter',
 templateUrl: './counter.component.html',
 styleUrls: ['./counter.component.scss']
})
export class CounterComponent implements OnInit {
 countNumber: number = 0;
 constructor() { }
 ngOnInit() {
 }
 onIncrease() {
 this.countNumber++;
 }
 onDecrease() {
 this.countNumber--;
 }
}
3.1.1 기능 설명
증가 단 추 를 눌 렀 을 때 현재 계수 가 1 증가 하고 감소 단 추 를 눌 렀 을 때 현재 계수 가 1 증가 합 니 다.
 
3.1.2 다른 구성 요소 에서 직접 사용 할 때 오류 가 발생 합 니 다.
 
오류 보고 정 보 는 다음 과 같다.
 
오류 정 보 는 우리 가 사용 하 는 구성 요소가 폼 컨트롤 이 아니 라 는 것 입 니 다.
3.2구성 요 소 를 폼 컨트롤 구성 요소 로 만 드 는 방법
3.2.1 ControlValueAccessor 인터페이스 실현
 

export class CounterComponent implements OnInit, ControlValueAccessor {
 countNumber: number = 0;
 constructor() { }
 ngOnInit() {
 }
 onIncrease() {
 this.countNumber++;
 }
 onDecrease() {
 this.countNumber--;
 }
 /**            */
 writeValue(obj: any): void {
 }
 /**            */
 registerOnChange(fn: any): void {
 }
 registerOnTouched(fn: any): void {
 }
 setDisabledState?(isDisabled: boolean): void {
 }
}
3.2.2 의존 정보 제공 자 지정
 

import { Component, OnInit, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
 selector: 'app-counter',
 templateUrl: './counter.component.html',
 styleUrls: ['./counter.component.scss'],
 providers: [
 {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => CounterComponent),
  multi: true
 }
 ]
})
export class CounterComponent implements OnInit, ControlValueAccessor {
 countNumber: number = 0;
 constructor() { }
 ngOnInit() {
 }
 onIncrease() {
 this.countNumber++;
 }
 onDecrease() {
 this.countNumber--;
 }
 /**            */
 writeValue(obj: any): void {
 }
 /**            */
 registerOnChange(fn: any): void {
 }
 registerOnTouched(fn: any): void {
 }
 setDisabledState?(isDisabled: boolean): void {
 }
}
3.2.3 복구 대기 버그
정상적으로 실행 할 수 있 지만 폼 컨트롤 의 요 소 는 폼 컨트롤 을 사용 하 는 구성 요소 에서 폼 모델 이 보 내 온 데 이 터 를 받 아들 일 수 없습니다.폼 컨트롤 이 변 한 데 이 터 는 폼 컨트롤 을 사용 하 는 구성 요소 의 폼 모델 로 전송 할 수 없습니다.한 마디 로 하면 모델 과 보기 사이 에 데이터 상호작용 을 할 수 없다 는 것 이다.
3.3 실습 모델 과 시도 한 데이터 의 상호작용
3.3.1 모델 보기
사용자 정의 폼 컨트롤 클래스 의 writeValue 방법 을 재 구성 합 니 다.
기교 01:writeValue 방법의 매개 변 수 는 사용자 정의 폼 컨트롤 을 사용 하 는 그 구성 요소 가 폼 의 데이터 바 인 딩 을 통 해 전 달 됩 니 다.
 
3.3.2 모델 로 보기
사용자 정의 폼 컨트롤 의 변화 데 이 터 를 처리 하 는 방법 을 사용자 정의 합 니 다.

propagateChange = (_: any) => {};
사용자 정의 폼 컨트롤 클래스 의 registerOnChange 방법 재 구성

 /**            */
 registerOnChange(fn: any): void {
 this.propagateChange = fn;
 }
>데이터 가 변 하 는 곳 에서 사용자 정의 방법 을 호출 합 니 다.
 
3.4 사용자 정의 폼 컨트롤 구성 요소 코드 집합

<div>
 <h4>     :{{countNumber}}</h4>
 <br />
 <div>
 <button md-icon-button (click)="onIncrease()">
  <span>  </span>
  <md-icon>add</md-icon>
 </button>
 <span style="margin-left: 30px;"></span>
 <button md-icon-button (click)="onDecrease()">
  <span>  </span>
  <md-icon>remove</md-icon>
 </button>
 </div>
</div>
HTML

import { Component, OnInit, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
 selector: 'app-counter',
 templateUrl: './counter.component.html',
 styleUrls: ['./counter.component.scss'],
 providers: [
 {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => CounterComponent),
  multi: true
 }
 ]
})
export class CounterComponent implements OnInit, ControlValueAccessor {
 countNumber: number = 0;
 propagateChange = (_: any) => {};
 constructor() { }
 ngOnInit() {
 }
 onIncrease() {
 this.countNumber++;
 this.propagateChange(this.countNumber);
 }
 onDecrease() {
 this.countNumber--;
 this.propagateChange(this.countNumber);
 }
 /**            */
 writeValue(obj: any): void {
 this.countNumber = obj;
 }
 /**            */
 registerOnChange(fn: any): void {
 /**fn       ,              fn       ,                */
 this.propagateChange = fn; //  fn      this.propagateChange,                   this.propagateChange    
 }
 registerOnTouched(fn: any): void {
 }
 setDisabledState?(isDisabled: boolean): void {
 }
}
3.5 사용자 정의 폼 컨트롤 을 사용 하 는 그 구성 요소 의 코드 집합
기술 01:사용자 정의 폼 컨트롤 과 사용자 정의 폼 컨트롤 을 사용 하 는 구성 요소 가 같은 모듈 에 없 을 때 사용자 정의 폼 컨트롤 에 대응 하 는 구성 요 소 를 내 보 내 고 가 져 와 야 합 니 다.
 

<div class="panel panel-primary">
 <div class="panel-heading">    </div>
 <div class="panel-body">
 <h3>      </h3>
 </div>
 <div class="panel-footer">2018-1-22 10:22:20</div>
</div>

<div class="panel-primary">
 <div class="panel-heading">         </div>
 <div class="panel-body">
 <form #myForm=ngForm>
  <app-counter name="counter" [(ngModel)]="countNumber">
  </app-counter>
 </form>
 <h6>                   </h6>
 <hr style="border: solid green 2px" />
 <h6>                     </h6>
 <h3>       :{{myForm.value | json}}</h3>
 </div>
 <div class="panel-footer">2018-1-31 10:09:17</div>
</div>

<div class="panel-primary">
 <div class="panel-heading">      </div>
 <div class="panel-body">
 <form #form="ngForm">
  <p>outerCounterValue value: {{outerCounterValue}}</p>
  <app-exe-counter name="counter" [(ngModel)]="outerCounterValue"></app-exe-counter>
  <br />
  <button md-raised-button type="submit">Submit</button>
  <br />
  <div>
  {{form.value | json}}
  </div>
 </form>
 </div>
 <div class="panel-footer">2018-1-27 21:51:45</div>
</div>

<div class="panel panel-primary">
 <div class="panel-heading">ngIf    </div>
 <div class="panel-body">
 <button md-rasied-button (click)="onChangeNgifValue()">  ngif  </button>
 <br />
 <div *ngIf="ngif; else ngifTrue" >
  <h4 style="background-color: red; color: white" >ngif     true</h4>
 </div>
 <ng-template #ngifTrue>
  <h4 style="background-color: black; color: white">ngif     false</h4>
 </ng-template>
 </div>
 <div class="panel-footer">2018-1-27 16:58:17</div>
</div>

<div class="panel panel-primary">
 <div class="panel-heading">RXJS  </div>
 <div class="panel-body">
 <h4>    </h4>
 </div>
 <div class="panel-footer">2018-1-23 21:14:49</div>
</div>

<div class="panel panel-primary">
 <div class="panel-heading">      </div>
 <div class="panel-body">
 <form (ngSubmit)="onTestLogin()" [formGroup]="loginForm">
  <md-input-container>
  <input mdInput placeholder="      " formControlName="username" />
  </md-input-container>
  <br />
  <md-input-container>
  <input mdInput placeholder="     " formControlName="userpwd" />
  </md-input-container>
  <br />
  <button type="submit" md-raised-button>  </button>
 </form>
 </div>
 <div class="panel-footer">2018-1-23 11:06:01</div>
</div>

<div class="panel panel-primary">
 <div class="panel-heading">     </div>
 <div class="panel-body">
 <form [formGroup]="testForm">
  <md-input-container>
  <input mdInput type="text" placeholder="     " formControlName="email" />
  <span mdSuffix>@163.com</span> 
  </md-input-container>
  <br />
  <md-input-container>
  <input mdInput type="password" placeholder="     " formControlName="password" />
  </md-input-container>
 </form>
 <hr />
 <div>
  <h2>        :</h2>
  <h4>       :{{testForm.valid}}</h4>
  <h4>     :{{testForm.value | json}}</h4>
  <h4>       FormControl:{{testForm.controls['email'] }}</h4>
  <hr />
  <h2>email        :</h2>
  <h4>   :{{testForm.get('email').valid}}</h4>
  <h4>email         :{{testForm.get('email').errors | json}}</h4>
  <h4>required    :{{testForm.hasError('required', 'email') | json}}</h4>
  <h4>minLength    :{{ testForm.hasError('minLength', 'email') | json }}</h4>
  <h4>hello:{{ testForm.controls['email'].errors | json }}</h4>
  <hr />
  <h2>password         :</h2>
  <h4>   :{{testForm.get('password').valid}}</h4>
  <h4>password         :{{testForm.get('password').errors | json }}</h4>
  <h4>required    :{{testForm.hasError('required', 'password') | json}}</h4>
 </div>
 <div>
  <button nd-rasied-button (click)="onTestClick()">    </button>
  <h4>data  :{{data}}</h4>
 </div>
 </div>
 <div class="panel-footer">2018-1-22 15:58:43</div>
</div>

<div class="panel panel-primary">
 <div class="panel-heading">                 </div>
 <div class="panel-body">
 <md-input-container>
  <input mdInput placeholder="     (       ):" [formControl]="name"/>
 </md-input-container>
 <div>
     :{{name.value}}
 </div>
 </div>
 <div class="panel-footer">2018-1-22 11:12:35</div>
</div> -->

<div class="panel panel-primary">
 <div class="panel-heading">    </div>
 <div class="panel-body">
 <md-input-container>
  <input mdInput placeholder="       " #a="ngModel" [(ngModel)]="desc" name="desc" />
  <button type="button" md-icon-button mdSuffix (click)="onTestNgModelClick()">
  <md-icon>done</md-icon>
  </button>
 </md-input-container>
 <div>
  <h3>  desc        :{{ a.value }}</h3>
 </div>
 </div>
 <div class="panel-footer">2018-1-22 10:19:31</div>
</div>

<div class="panel panel-primary">
 <div class="panel-heading">md-chekbox   </div>
 <div calss="panel-body">
 <div>
  <md-checkbox #testCheckbox color="primary" checked="true">  </md-checkbox>
 </div>
 <div *ngIf="testCheckbox.checked">
  <h2>  checkbox    </h2>
 </div>
 </div>
 <div class="panel-footer">2018-1-18 14:02:20</div>
</div> 

<div class="panel panel-primary">
 <div class="panel-heading">md-tooltip   </div>
 <div class="panel-body">
 <span md-tooltip="    ">     </span>
 </div>
 <div class="panel-footer">2018-1-18 14:26:58</div>
</div>


<div class="panel panel-primary">
 <div class="panel-heading">md-select   </div>
 <div class="panel-body">
 <md-select placeholder="       " class="fill-width" style="height: 40px;">
  <md-option *ngFor="let taskList of taskLists" [value]="taskList.name">{{taskList.name}}</md-option>
 </md-select>
 </div>
 <div class="panel-footer">2018-1-18 14:26:58</div>
</div> 

<div class="panel panel-primary">
 <div class="panel-heading">ngNonBindable     </div>
 <div class="panel-body">
 <h3>  </h3>
 <p>   ngNonBindable   ,                     </p>
 <h3>  </h3>
 <p>
  <span>{{taskLists | json }}</span>
  <span ngNonBindable>←   {{taskLists | json }}     </span>
 </p>
 </div>
 <div class="panel-footer">2018-1-19 09:34:26</div>
</div>
HTML
 

import { Component, OnInit, HostListener, Inject} from '@angular/core';
import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Http } from '@angular/http';
import { QuoteService } from '../../service/quote.service';
@Component({
 selector: 'app-test01',
 templateUrl: './test01.component.html',
 styleUrls: ['./test01.component.scss']
})
export class Test01Component implements OnInit {
 countNumber: number = 9;
 outerCounterValue: number = 5; 
 ngif = true;
 loginForm: FormGroup;
 testForm: FormGroup;
 data: any;
 name: FormControl = new FormControl();
 desc: string = 'hello boy';
 taskLists = [
 {label: 1, name: '   '},
 {label: 2, name: '   '}
 ];
 constructor(
 private formBuilder: FormBuilder,
 private http: Http,
 @Inject('BASE_CONFIG') private baseConfig,
 private quoteService: QuoteService
 ) {}
 ngOnInit() {
 this.testForm = new FormGroup({
  email: new FormControl('', [Validators.required, Validators.minLength(4)], []),
  password: new FormControl('', [Validators.required], [])
 });
 this.name.valueChanges
 .debounceTime(500)
 .subscribe(value => alert(value));
 this.loginForm = this.formBuilder.group({
  username: ['', [Validators.required, Validators.minLength(4), this.myValidator], []],
  userpwd: ['', [Validators.required, Validators.minLength(6)], []]
 });
 this.quoteService.test()
 .subscribe(resp => console.log(resp));
 }
 onChangeNgifValue() {
 if (this.ngif == false) {
  this.ngif = true;
 } else {
  this.ngif = false;
 }
 }
 @HostListener('keyup.enter')
 onTestNgModelClick() {
 alert('  ');
 }
 onTestClick() {
 // this.data = this.testForm.get('email').value;
 // console.log(this.testForm.getError);
 console.log(this.testForm.controls['email']);
 }
 onTestLogin() {
 console.log(this.loginForm.value);
 if (this.loginForm.valid) {
  console.log('      ');
 } else {
  console.log('       ');
  console.log(this.loginForm.controls['username'].errors);
  console.log(this.loginForm.get('userpwd').errors);
 }
 }
 myValidator(fc: FormControl): {[key: string]: any} {
 const valid = fc.value === 'admin';
 return valid ? null : {myValidator: {requiredUsername: 'admin', actualUsername: fc.value}};
 }
}
3.6 초기 화 효과 전시
 

좋은 웹페이지 즐겨찾기