Angular 2 NgForm에서 터치된 이벤트를 관찰하는 방법은 무엇입니까?
에 대한 콜백을 구독할 수 있습니다.NgForm의valueChanges양식 컨트롤의 값 변화에 대응하기 위해 관찰 가능한 속성입니다.
같은 방식으로 사용자가 양식 컨트롤 중 하나를 터치하는 경우에도 대응해야 합니다.
이 클래스는 다음을 정의하는 것 같습니다.valueChanges관찰 가능 및touched속성이 부울로 정의되었습니다.
"컨트롤 터치" 이벤트에 대응할 수 있는 방법이 있습니까?
기본값을 확장할 수 있습니다.FormControl클래스, 추가markAsTouched네이티브 메소드를 호출하는 메소드와 당신의 부작용을 추가됩니다.
import { Injectable } from '@angular/core';
import { FormControl, AsyncValidatorFn, ValidatorFn } from '@angular/forms';
import { Subscription, Subject, Observable } from 'rxjs';
export class ExtendedFormControl extends FormControl {
statusChanges$: Subscription;
touchedChanges: Subject<boolean> = new Subject<boolean>();
constructor(
formState: Object,
validator: ValidatorFn | ValidatorFn[] = null,
asyncValidator: AsyncValidatorFn | AsyncValidatorFn[] = null
) {
super(formState, validator, asyncValidator);
this.statusChanges$ = Observable.merge(
this.valueChanges,
this.touchedChanges.distinctUntilChanged()
).subscribe(() => {
console.log('new value or field was touched');
});
}
markAsTouched({ onlySelf }: { onlySelf?: boolean } = {}): void {
super.markAsTouched({ onlySelf });
this.touchedChanges.next(true);
}
}
ng2가 터치된 이벤트에 반응할 수 있는 직접적인 방법은 없습니다.(입력) 이벤트를 사용하여 값 Changes 이벤트를 발생시키고 (흐림) 이벤트를 사용하여 AbstractControl의 touched/untouched 속성을 설정합니다.따라서 템플릿에서 원하는 이벤트를 수동으로 구독하고 구성 요소 클래스에서 처리해야 합니다.
동일한 문제가 발생했습니다. 이 도우미 방법을 함께 사용하여 터치 상태가 변경될 때 알림을 받을 수 있는 양식으로 구독할 수 있는 관찰 항목을 추출합니다.
// Helper types
/**
* Extract arguments of function
*/
export type ArgumentsType<F> = F extends (...args: infer A) => any ? A : never;
/**
* Creates an object like O. Optionally provide minimum set of properties P which the objects must share to conform
*/
type ObjectLike<O extends object, P extends keyof O = keyof O> = Pick<O, P>;
/**
* Extract a touched changed observable from an abstract control
* @param control AbstractControl like object with markAsTouched method
*/
export const extractTouchedChanges = (control: ObjectLike<AbstractControl, 'markAsTouched' | 'markAsUntouched'>): Observable<boolean> => {
const prevMarkAsTouched = control.markAsTouched.bind(control);
const prevMarkAsUntouched = control.markAsUntouched.bind(control);
const touchedChanges$ = new Subject<boolean>();
function nextMarkAsTouched(...args: ArgumentsType<AbstractControl['markAsTouched']>) {
prevMarkAsTouched(...args);
touchedChanges$.next(true);
}
function nextMarkAsUntouched(...args: ArgumentsType<AbstractControl['markAsUntouched']>) {
prevMarkAsUntouched(...args);
touchedChanges$.next(false);
}
control.markAsTouched = nextMarkAsTouched;
control.markAsUntouched = nextMarkAsUntouched;
return touchedChanges$;
}
// Usage (in component file)
...
this.touchedChanged$ = extractTouchedChanges(this.form);
...
나는 그럼 하는 것을 좋아합니다.merge(this.touchedChanged$, this.form.valueChanges)유효성 검사를 업데이트하는 데 필요한 모든 변경 사항을 관찰할 수 있습니다.
*편집 - @marked-down의 제안으로 새 값을 받은 후 바로 쿼리하여 동기화되지 않을 경우를 대비하여 새 값을 내보내기 전의 함수로 통화를 이동했습니다.
만약 당신의 문제가 나의 문제와 같다면, 나는 한 구성 요소에서 필드를 터치한 것으로 표시한 다음 다른 구성 요소에서 응답하려고 했습니다.나는 접근 권한이 있었습니다.AbstractControl그 방면에.내가 그것을 피하는 방법은
field.markAsTouched();
(field.valueChanges as EventEmitter<any>).emit(field.value);
그런 다음 다른 구성 요소에서 valueChanges를 구독했습니다.주목할 점:field.valueChanges관찰할 수 있는 항목으로 내보내지만 런타임에EventEmitter이것을 덜 아름다운 해결책으로 만드는 것.이것의 또 다른 한계는 분명히 여러분이 단지 만진 상태 이상의 것을 구독하고 있다는 사실일 것입니다.
이 방법으로 해결했습니다.
this.control['_markAsTouched'] = this.control.markAsTouched;
this.control.markAsTouched = () => {
this.control['_markAsTouched']();
// your event handler
}
기본적으로 기본값을 덮어쓰고 있습니다.markAsTouched의 방법FormControl.
여기 제가 생각해 낸 util 기능이 있습니다, 그것은 또한 듣습니다.reset메서드 및 컨트롤을 그대로 유지합니다.
/**
* Allows to listen the touched state change.
* The util is needed until Angular allows to listen for such events.
* Https://github.com/angular/angular/issues/10887.
* @param control Control to listen for.
*/
export function listenControlTouched(
control: AbstractControl,
): Observable<boolean> {
return new Observable<boolean>(observer => {
const originalMarkAsTouched = control.markAsTouched;
const originalReset = control.reset;
control.reset = (...args) => {
observer.next(false);
originalReset.call(control, ...args);
};
control.markAsTouched = (...args) => {
observer.next(true);
originalMarkAsTouched.call(control, ...args);
};
observer.next(control.touched);
return () => {
control.markAsTouched = originalMarkAsTouched;
control.reset = originalReset;
};
});
}
언급URL : https://stackoverflow.com/questions/41337024/how-to-observe-touched-event-on-angular-2-ngform
'programing' 카테고리의 다른 글
| 간단한 SQL 코드로 마리아DB의 NOCYLE(오라클) 계층 쿼리를 사용하여 CONNECT BY (0) | 2023.06.11 |
|---|---|
| C#을 사용하여 메서드를 매개 변수로 전달 (0) | 2023.06.11 |
| 판다의 다른 값을 기준으로 한 값 변경 (0) | 2023.06.11 |
| 미들웨어에서 Vuex로 상태가 업데이트되지 않습니까? (0) | 2023.06.11 |
| 도구 모음에 뒤로 화살표 표시 (0) | 2023.06.06 |