Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- angular modal
- Oracle LISTAGG 사용 예시
- ApexChart
- angular animation
- route
- 스크롤 이벤트 감지
- 앵귤러 모달
- flex-1
- modal
- TAILWIND
- 옵저버블
- angular button
- 아이오닉 스크롤 이벤트
- Router
- angular route
- formgroup
- ajax 사용 예시
- 호버
- mysql if
- prisma
- summary
- 모달
- scroll
- Angular Router
- egov spring ajax 사용 예시
- 셀렉트박스 커스텀
- 검색
- Ionic modal
- 앵귤러 애니메이션
- 스크롤 이벤트
Archives
- Today
- Total
깜놀하는 해므찌로
ControlValueAccessor Angular 사용 예시 / CustomValueAccessor 본문
반응형
SMALL
import { AbstractControl, ControlValueAccessor, ValidationErrors, Validator } from "@angular/forms";
export class CustomValueAccessor<T> implements ControlValueAccessor, Validator {
disabled = false;
required: boolean = false;
touched: boolean = false;
onChange: any = (value: T) => { };
onTouched: any = () => { };
onValidationchange: any = () => { };
private _value!: T;
set value(newValue: T) {
if (this._value === newValue) { return; }
this._value = newValue;
this.onChange(newValue);
this.onTouched();
this.touched = true // 이벤트 트리거 시 컨트롤 표시
}
get value(): T {
return this._value;
}
writeValue(value: T): void {
this.value = value;
}
registerOnChange(fn: (value: T) => {}): void {
this.onChange = fn;
}
registerOnTouched(fn: () => {}): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}
validate(control: AbstractControl<any, any>): ValidationErrors | null {
return this.required && this.touched ? !this._value ? { required: true } : null : null
}
registerOnValidatorChange?(fn: () => void): void {
this.onValidationchange = fn
}
}
1. 커스텀 컨트롤 엑세스
<input
#input
[disabled]="disabled"
[(ngModel)]="value"
[maxlength]="maxlength ?? null"
[placeholder]="placeholder ?? ''"
[autofocus]="_autofocus"
oninput="this.value = this.value.replace(/[^0-9.]/g, '')
.replace(/(\..*)\./g, '$1')
.replace(/^(\d{0,3})(\d{0,4})(\d{0,4})$/, `$1-$2-$3`)
.replace(/\-{1,2}$/g, '');"
class="w-full px-3 py-2.5 text-sm border outline-none border-gray-200 hover:border-gray-500 focus-within:border-gray-500 rounded-md"
/>
import { ReactiveFormsModule, NgControl, FormsModule } from '@angular/forms';
import {
Component,
Input,
ElementRef,
Optional,
Self,
ViewChild,
} from '@angular/core';
import { CustomValueAccessor } from '../custom-value-accessor';
@Component({
selector: 'app-input-tel',
templateUrl: './input-tel.component.html',
styleUrls: ['./input-tel.component.scss'],
standalone: true,
imports: [ReactiveFormsModule, FormsModule],
})
export class InputTelComponent extends CustomValueAccessor<string> {
_autofocus: boolean = false;
@ViewChild('input') input: ElementRef<HTMLInputElement> | undefined;
@Input() class?: string | undefined;
@Input() id?: string | undefined;
@Input() formControlName?: string | undefined;
@Input() fixText?: string | undefined;
@Input() maxlength?: string | number | null;
@Input() placeholder?: string | undefined;
@Input() override required: boolean = false;
@Input()
set autofocus(value: string | boolean) {
this._autofocus = typeof value === 'string' ? value !== undefined : value;
}
constructor(@Self() @Optional() public ngControl: NgControl) {
super();
if (this.ngControl) {
this.ngControl.valueAccessor = this;
}
}
get invalid(): boolean {
return (this.ngControl?.dirty ?? false) && !this.ngControl?.valid;
}
}
<app-input-tel
placeholder="지점 대표번호를 입력해주세요"
formControlName="representativeTel"
maxlength="13"
/>
2. 단일 input 템플릿 및 컴포넌트 (핸드폰 번호만 받기)
<app-input-tel
formControlName="tel"
placeholder="숫자로만 입력해주세요"
maxlength="13"
class="w-full rounded-md border border-gray-200"
/>
3. input 컴포넌트를 장착하는 템플릿 예시
<input
#input
[disabled]="disabled"
[type]="type"
[(ngModel)]="value"
[maxlength]="maxlength ?? null"
[placeholder]="placeholder ?? ''"
[autofocus]="_autofocus"
class="w-full px-3 py-2.5 text-sm border outline-none border-gray-200 hover:border-gray-500 focus-within:border-gray-500 rounded-md"
/>
import {
Component,
ElementRef,
Input,
Optional,
Self,
ViewChild,
} from '@angular/core';
import { FormsModule, NgControl } from '@angular/forms';
import { CustomValueAccessor } from '../custom-value-accessor';
@Component({
selector: 'app-input-text',
templateUrl: './input-text.component.html',
styleUrls: ['./input-text.component.scss'],
imports: [FormsModule],
standalone: true,
})
export class InputTextComponent extends CustomValueAccessor<string> {
_autofocus: boolean = false;
@ViewChild('input') input: ElementRef<HTMLInputElement> | undefined;
@Input() label?: string;
@Input() icon?: string;
@Input() placeholder?: string;
@Input() fixText?: string;
@Input() debounce?: number;
@Input() type?: 'text' | 'password' = 'text';
@Input() maxlength?: string | number | null;
@Input() override required: boolean = false;
@Input()
set autofocus(value: string | boolean) {
this._autofocus = typeof value === 'string' ? value !== undefined : value;
}
get invalid(): boolean {
return (this.ngControl?.dirty ?? false) && !this.ngControl?.valid;
}
constructor(@Self() @Optional() public ngControl: NgControl) {
super();
if (this.ngControl) {
this.ngControl.valueAccessor = this;
}
}
}
4. 단일 컴포넌트 text 타입 예시
import {
Component,
Input,
ElementRef,
Optional,
Self,
ViewChild,
} from '@angular/core'; // custom
import { FormsModule, NgControl, ReactiveFormsModule } from '@angular/forms'; // custom
import { CustomValueAccessor } from '../custom-value-accessor'; // custom
@Component({
selector: 'app-input-text',
templateUrl: './input-text.component.html',
styleUrls: ['./input-text.component.scss'],
standalone: true,
imports: [FormsModule, ReactiveFormsModule],
})
export class InputTextComponent extends CustomValueAccessor<string> {
// custom
// ViewChild decorator : 자식 컴포넌트, 디렉티브, rendered Dom 에 직접 접근이 가능하도록 함 -> 데이터 전송 가능
// 부모 Component template안에 위치한 모든 자식 요소들을 ViewChild라고 합니다.
// 부모 Component와 자식 Component가 데이터를 공유하는게 아니라 부모 Component가 직접 자식 Component 객체를 제어하는 방식입니다.
_autofocus: boolean = false;
// ElementRef : Template Reference Variable을 이용해서 해당 Element의 Reference를 획득,
// ElementRef type의 객체를 획득 nativeElement 속성으로 직접 제어할 수 있음!! -> rendered Dom 제어
@ViewChild('input') input: ElementRef<HTMLInputElement> | undefined;
@Input() class?: string | undefined;
@Input() id?: string | undefined;
@Input() formControlName?: string | undefined;
@Input() fixText?: string | undefined;
@Input() maxlength?: string | number | null;
@Input() placeholder?: string | undefined;
@Input() override required: boolean = false;
@Input()
set autofocus(value: string | boolean) {
this._autofocus = typeof value === 'string' ? value !== undefined : value;
}
// @Optional : 프로퍼티 데코레이터를 사용하면 의존성 객체를 찾지 못했을 때 에러를 발생하는 대신 null을 주입합니다.
constructor(@Self() @Optional() public ngControl: NgControl) {
super(); // custom
if (this.ngControl) {
// NgControl : It binds a FormControl object to a DOM element
this.ngControl.valueAccessor = this; // valueAccessor : ControlValueAccessor | null : The value accessor for the control
}
}
get invalid(): boolean {
// dirty : Reports whether the control is dirty,
// meaning that the user has changed the value in the UI. If the control is not present, null is returned.
return (this.ngControl?.dirty ?? false) && !this.ngControl?.valid;
// valid : A control is considered valid if no validation errors exist with the current value. If the control is not present, null is returned.
}
}
5. 상세 설명 버전
반응형
LIST
'IT' 카테고리의 다른 글
modal 범위를 벗어나 화면 잘릴 시 css (0) | 2023.04.24 |
---|---|
modal 범위를 벗어나 화면 잘릴 시 css (0) | 2023.04.24 |
Angular [()] / 양방향 바인딩 (0) | 2023.04.24 |
ApexChart Angular 사용 예시 (0) | 2023.04.23 |
C언어 조합공식 + 재귀함수 사용 예시 (1) | 2023.04.22 |