Angular4 - 폼 제어를 위한 값 접근기 없음
커스텀 요소가 있습니다.
<div formControlName="surveyType">
<div *ngFor="let type of surveyTypes"
(click)="onSelectType(type)"
[class.selected]="type === selectedType">
<md-icon>{{ type.icon }}</md-icon>
<span>{{ type.description }}</span>
</div>
</div>
formControlName을 추가하려고 하면 다음 오류 메시지가 나타납니다.
오류:이름이 'survey'인 폼 제어에 대한 값 액세스자가 없습니다.타입'
ngDefaultControl
선택이 것 . 할지 요.어떻게 해야 할지 모르겠어요
누군가 카드 전체를 클릭하면 FormControl에 '타입'이 푸시되도록 이 FormControl에 클릭을 바인딩하고 싶습니다.가능합니까?
하시면 됩니다.formControlName
를 실장하는 지시에 한합니다.
인터페이스의 실장
따라서 원하는 작업을 수행하려면 구현 컴포넌트를 작성해야 합니다.즉, 다음 3가지 기능을 구현해야 합니다.
writeValue
(Angular에 모델에서 뷰로 값을 쓰는 방법을 알려 줍니다.)registerOnChange
되었을 때registerOnTouched
(컴포넌트가 터치이벤트를 수신했을 때 호출되는 핸들러를 설정해, 컴포넌트의 포커스가 설정되어 있는지를 확인하는 데 도움이 됩니다).
프로바이더 등록
이 는 Angular에게 이 을 .ControlValueAccessor
(인터페이스는 TypeScript가 JavaScript로 컴파일될 때 코드에서 삭제되므로 절단되지 않습니다).프로바이더를 등록하면 됩니다.
공급자는 기존 값을 제공하고 사용해야 합니다.여기도 필요합니다.주의:NG_VALUE_ACCESSOR
멀티 프로바이더여야 합니다.
를 들어Component인 MyControl Component로 에 다음 .@Component
★★★★★★★★★★★★★★★★★★:
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => MyControlComponent),
}
]
사용.
구성 요소를 사용할 준비가 되었습니다.템플릿 기반 폼에서는ngModel
이제 바인딩이 제대로 작동합니다.
반응형 폼을 사용하여 이제 올바르게 사용할 수 있습니다.formControlName
폼 컨트롤은 예상대로 동작합니다.
자원.
하면 됩니다.formControlName="surveyType"
input
이 아니라div
이 앵글을 때 는 뜻입니다formControl
div
이 문제를 해결하려면 두 가지 옵션이 있습니다.
- 네가 넣어.
formControlName
, 에서 Angular는 Angular를 사용합니다. 것들이 있습니다.input
,textarea
★★★★★★★★★★★★★★★★★」select
. - '하다'를 합니다.
ControlValueAccessor
인터페이스입니다.이렇게 하면 Angular에게 "컨트롤의 값에 액세스하는 방법"(이름을 따옴)을 알려주는 것입니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★formControlName
자연히 관련된 가치를 갖지 않는 요소입니다.
그럼 이제 '' ''를하고,ControlValueAccessor
인터페이스는 처음에는 조금 부담스러울 수 있습니다.특히 이 문제에 대한 문서가 별로 없기 때문에 코드에 보일러 플레이트를 많이 추가해야 합니다.이 문제를 알기 쉬운 단계로 나누어 보겠습니다.
양식 컨트롤을 자체 구성요소로 이동
「 」를 실장하려면 , 「 」를 합니다.ControlValueAccessor
새로운 컴포넌트(또는 지시어)를 작성해야 합니다.폼 컨트롤과 관련된 코드를 이동합니다.이와 같이 재사용도 용이합니다.에 컨트롤이 있는 될 수 컴포넌트 내부에 컨트롤이 있기 때문에 ''을 .ControlValueAccessor
그렇지 않으면 사용자 지정 구성 요소를 Angular 양식과 함께 사용할 수 없기 때문입니다.
코드에 보일러 플레이트 추가
의 ControlValueAccessor
인터페이스는 매우 상세합니다.이치노
import {Component, OnInit, forwardRef} from '@angular/core';
import {ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
@Component({
selector: 'app-custom-input',
templateUrl: './custom-input.component.html',
styleUrls: ['./custom-input.component.scss'],
// a) copy paste this providers property (adjust the component name in the forward ref)
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true
}
]
})
// b) Add "implements ControlValueAccessor"
export class CustomInputComponent implements ControlValueAccessor {
// c) copy paste this code
onChange: any = () => {}
onTouch: any = () => {}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouch = fn;
}
// d) copy paste this code
writeValue(input: string) {
// TODO
}
그러면 개별 부품은 무엇을 하고 있을까요?
- 시 Angular에게 a) Angular를 .
ControlValueAccessor
- b) 를 것을 합니다.
ControlValueAccessor
- 이수 .c) 이 부분이 가장 혼란스러울 수 있습니다.Angular에게 수 있는
onChange
★★★★★★★★★★★★★★★★★」onTouch
실행 시 자체 구현이 가능하므로 이러한 함수를 호출할 수 있습니다.이 점을 이해하는 것이 중요합니다.최초 빈 구현 이외에는 onChange 및 onTouch를 직접 구현할 필요가 없습니다.당신이 (c)와 함께 하는 유일한 일은 Angular가 당신의 클래스에 자신의 함수를 부가하게 하는 것이다. 왜?그러면 전화할 수 있습니다.onChange
★★★★★★★★★★★★★★★★★」onTouch
적절한 시간에 Angular에서 제공하는 방법.아래에서 어떻게 되는지 알아보겠습니다. - d) 또, 델이 어떻게
writeValue
방법은 다음 섹션에서 구현 시 사용할 수 있습니다.여기에 두었으니까 필요한 모든 속성들은ControlValueAccessor
이치노
write Value 구현
what?writeValue
폼 컨트롤이 외부에서 변경되었을 때 커스텀컴포넌트 내부에서 작업을 수행합니다.예를 들어 사용자 정의 양식 제어 구성 요소의 이름을 지정한 경우app-custom-input
부모 컴포넌트에서는 다음과 같이 사용합니다.
<form [formGroup]="form">
<app-custom-input formControlName="myFormControl"></app-custom-input>
</form>
writeValue
마다 트리거됩니다.myFormControl
폼 : 폼 초기화 중)일 수this.form = this.formBuilder.group({myFormControl: ""});
폼리셋 시) "" " " " " " 。this.form.reset();
.
일반적으로 양식 컨트롤 값이 외부에서 변경되면 양식 컨트롤 값을 나타내는 로컬 변수에 씁니다.를 들어, '하다'가 '하다'라고 ,CustomInputComponent
컨트롤을 수 있습니다.
writeValue(input: string) {
this.input = input;
}
「html」의합니다.CustomInputComponent
:
<input type="text"
[ngModel]="input">
또한 Angular 문서에 설명된 대로 입력 요소에 직접 쓸 수도 있습니다.
이것으로 외부에서 무언가가 변경되었을 때 컴포넌트 내부에서 일어나는 일을 처리했습니다.이제 다른 방향을 봅시다.컴포넌트 내부에 변화가 생겼을 때 어떻게 외부에 알립니까?
변경 시 호출
는 부모 입니다.CustomInputComponent
onChange
★★★★★★★★★★★★★★★★★」onTouch
(c) 위로부터의 기능이 작용한다.이러한 함수를 호출하면 컴포넌트 내부의 변경 사항을 외부에 알릴 수 있습니다.값의 변경을 외부에 전파하려면 새로운 값을 인수로 하여 onChange를 호출해야 합니다.예를 들어, 사용자가 에 무언가를 입력한 경우input
컴포넌트의 에서는, 「」를 합니다.onChange
다음 값을 사용합니다.
<input type="text"
[ngModel]="input"
(ngModelChange)="onChange($event)">
일이 있는지 수 는 자신의 각도로 바인드되어 있는 것은 이 실장입니다.onChange
클래스 속성이 실장에서는 1개의 인수(갱신된 제어값)가 필요합니다.지금 당신이 하고 있는 일은 그 방법을 호출하고 Angular에게 변경에 대해 알리는 것입니다.이제 Angular가 진행되어 바깥쪽 폼 값이 변경됩니다.이게 이 모든 것의 핵심이야.를 호출하여 폼 컨트롤을 갱신해야 하는 시기와 값을 Angular에 알렸습니다."관리 값에 액세스"할 수 있는 수단을 제공했습니다.
: 이름onChange
예를 들어 어떤 것이든 할 수 .propagateChange
또는 이와 유사합니다. 이름을 와 Angular에서 를 사용할 수 .registerOnChange
실행 시 메서드를 사용합니다.
온터치 호출
양식 컨트롤은 "터치"할 수 있으므로 사용자 정의 양식 컨트롤이 터치된 시점을 이해하는 수단도 Angular에 제공해야 합니다.수 할 수 있다, 할 수 있다, 할 수 있다, 할 수 있다, 할 수 있다.onTouch
할 수 있는하고 있는지 Angular로 전화해야 합니다.onTouch
" " " 력드가가드가 。
<input type="text"
[(ngModel)]="input"
(ngModelChange)="onChange($event)"
(blur)="onTouch()">
한 번, 하다.onTouch
제가 고른 이름인데, 실제 기능은 앵글이 제공하고 인수가 필요 없습니다.앵글에게 방금 알려줬으니 폼 컨트롤이 만졌다는 게 말이 되네
모든 것을 종합하면
다 합쳐서 어떤 느낌일까요?다음과 같이 표시됩니다.
// custom-input.component.ts
import {Component, OnInit, forwardRef} from '@angular/core';
import {ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
@Component({
selector: 'app-custom-input',
templateUrl: './custom-input.component.html',
styleUrls: ['./custom-input.component.scss'],
// Step 1: copy paste this providers property
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomInputComponent),
multi: true
}
]
})
// Step 2: Add "implements ControlValueAccessor"
export class CustomInputComponent implements ControlValueAccessor {
// Step 3: Copy paste this stuff here
onChange: any = () => {}
onTouch: any = () => {}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouch = fn;
}
// Step 4: Define what should happen in this component, if something changes outside
input: string;
writeValue(input: string) {
this.input = input;
}
// Step 5: Handle what should happen on the outside, if something changes on the inside
// in this simple case, we've handled all of that in the .html
// a) we've bound to the local variable with ngModel
// b) we emit to the ouside by calling onChange on ngModelChange
}
// custom-input.component.html
<input type="text"
[(ngModel)]="input"
(ngModelChange)="onChange($event)"
(blur)="onTouch()">
// parent.component.html
<app-custom-input [formControl]="inputTwo"></app-custom-input>
// OR
<form [formGroup]="form" >
<app-custom-input formControlName="myFormControl"></app-custom-input>
</form>
기타 예
- 입력 예: https://stackblitz.com/edit/angular-control-value-accessor-simple-example-tsmean
- Lazy Loaded 입력 예시:https://stackblitz.com/edit/angular-control-value-accessor-lazy-input-example-tsmean
- 버튼의 예: https://stackblitz.com/edit/angular-control-value-accessor-button-example-tsmean
중첩된 양식
Control Value Accessors: 값 접근자 제어폼에는, 「」를 할 수 .@Input() subform
Control 는 Control Value Accessor를 랩하는 것을 합니다.controls
아니라, 이에요.groups
! 네스트된 형식의 입력을 사용하는 예를 참조하십시오.https://stackblitz.com/edit/angular-nested-forms-input-2
원천
- https://angular.io/api/forms/ControlValueAccessor
- https://www.tsmean.com/articles/angular/angular-control-value-accessor-example/
이것은 Angular가 이러한 유형의 제어에 대해 서로 다른 ValueAccessor를 가지고 있기 때문에 선택한 입력 컨트롤의 "복수" 속성 때문입니다.
const countryControl = new FormControl();
그리고 내부 템플릿은 이렇게 사용합니다.
<select multiple name="countries" [formControl]="countryControl">
<option *ngFor="let country of countries" [ngValue]="country">
{{ country.name }}
</option>
</select>
언급URL : https://stackoverflow.com/questions/45659742/angular4-no-value-accessor-for-form-control
'programing' 카테고리의 다른 글
불변성 실패:외부에서는 사용하지 마십시오. (0) | 2023.04.02 |
---|---|
Woocommerce: 순서대로 총 항목 수 가져오기 (0) | 2023.04.02 |
WooCommerce 미니카트를 WordPress 사이트에 표시할 수 있는 방법이 있습니까? (0) | 2023.04.02 |
useEffect 훅을 발생시킨 의존관계 배열 변수 확인 (0) | 2023.04.02 |
Flask RESTful 교차 도메인 문제 Angular: PUT, OPTIONS 메서드 (0) | 2023.04.02 |