codememo

각진 강한 유형의 반응형

tipmemo 2023. 7. 17. 21:08
반응형

각진 강한 유형의 반응형

Angular 프로젝트에서 FormGroups, FormArrays 및 FormControls를 강력하게 입력하기 위해 대규모 구성 요소 집합을 리팩터링하려고 합니다.

저는 강력한 유형의 반응형을 구현하는 좋은 방법을 찾고 있습니다.자신의 경험을 바탕으로 제안/권장 사항을 제시할 수 있는 사람이 있습니까?

감사해요.

편집:

즉, FormGroup 또는 FormArray를 만들 때 현재는 FormGroup 또는 FormArray 내부의 실제 양식 구조를 지정할 수 없습니다.이 양식을 앱의 다양한 구성 요소에 전달하면 유지 관리가 더 어려워지는 것 같습니다.

가장 우아한 솔루션은 TypeScript 선언 파일을 활용하는 것입니다.*.d.ts) 표준 양식 클래스를 확장하는 일반 인터페이스를 소개합니다.AbstractControl,FormControl기타. 컴파일된 JavaScript에 새로운 기능을 도입하지 않고 설치 공간이 없는 동시에 강력한 유형 검사를 시행합니다.

다니엘레 모로시노토가 올해 3월에 제안했고 Angular 9에 포함시키기 위해 현재 논의 입니다.

솔루션 채택은 간단합니다.

  1. 다운로드.TypedForms.d.ts이 요점으로부터 그것을 저장합니다.src/typings.d.ts(Angular 6+는 이미 이 파일을 사용하는 방법을 알고 있습니다.)
  2. 새 유형 사용 시작(FormGroupTyped<T>,FormControlTyped<T>(등) 강력한 형식 검증이 필요할 때마다 (해당 요지 또는 스택 블리츠의 예 참조).

자세한 내용은 강력한 형식의 양식에 대한 사용 가능한 솔루션을 분석하는 블로그 게시물을 참조하십시오.

다른 해결책을 원하는 사람들을 위해.저는 이 기사가 각진 형태에 대한 강한 유형에 대해 이야기하는 것을 발견했습니다.아래는 제 요약입니다.

interface Person {
  name: string;
  email: string
}

// Controls in a form group that would emit a Person as it's value
type PersonControls = { [key in keyof Person]: AbstractControl };
type PersonFormGroup = FormGroup & { value: Person, controls: PersonControls };

export class MyFormComponent {
  form = new FormGroup({
    name: new FormControl(),
    email: new FormControl()
  } as PersonControls) as PersonFormGroup;

  init() {
    const name = this.form.controls.name; // strong typed!
  }
}

2022 업데이트(Angular 14):입력된 반응형 양식

Angular의 최신 업데이트를 통해 반응형 폼에 대한 엄격한 유형이 구현되었으며! 해결 방법이 필요하지 않습니다.

사용 중인 경우formBuilder양식 작성 서비스에서 다음과 같이 엄격한 유형을 지정할 수 있습니다.

type myType = 'typeA' | 'typeB' | 'typeC';

public myForm = this.fb.control<myType>('typeA');

다음을 생성하려는 경우 앙formGroup에 관계없이formBuilder서비스, 다음과 같은 이점을 얻을 수 있습니다.

interface User {
    name: FormControl<string>;
    email: FormControl<string>;
    isAdmin: FormControl<boolean>;
}

public user: FormGroup<User> = new FormGroup<User>({
    name: new FormControl('', {nonNullable: true}),
    email: new FormControl('', {nonNullable: true}),
    isAdmin: new FormControl(false, {nonNullable: true}),
});
다음을 지정하지 않을 경우 주의하십시오.nonNullable속성, 템플릿에서 값이 다음과 같은 오류가 발생할 수 있습니다.null특히 양식 컨트롤의 값을 어떤 것에 바인딩하려는 경우.

다음과 같이 유형을 명시적으로 기록하지 않더라도 Angular는 자동으로 유형 시스템을 확인합니다.

const cat = new FormGroup({
   name: new FormGroup({
      first: new FormControl('Barb'),
      last: new FormControl('Smith'),
   }),
   lives: new FormControl(9),
});

// Type-checking for forms values!
// TS Error: Property 'substring' does not exist on type 'number'.
let remainingLives = cat.value.lives.substring(1);

// Optional and required controls are enforced!
// TS Error: No overload matches this call.
cat.removeControl('lives');

// FormGroups are aware of their child controls.
// name.middle is never on cat
let catMiddleName = cat.get('name.middle');

이에 대한 자세한 내용은 블로그의 Angular 14 릴리스 업데이트에서 확인할 수 있습니다.

저도 비슷한 문제가 있었고 이것이 제 해결책이었습니다.저는 정말로 형태 자체가 아니라 형태의 '가치' 유형에만 관심이 있었습니다.결국 이런 꼴이 됐습니다.

export interface UserFormValue {
  first_name: string
  last_name: string
  referral: string
  email: string
  password: string
}
...

ngOnInit() {
  this.userForm = this.fb.group({
    first_name: [ '', Validators.required ],
    last_name: [ '', Validators.required ],
    referral: [ '' ],
    email: [ '', [ Validators.required, Validators.email ] ],
    password: [ '', [ Validators.required, Validators.minLength(8) ] ],
  });
}

...

그런 다음 템플릿에 값을 제출합니다.

<form [formGroup]="userForm" (ngSubmit)="onSubmit(userForm.value)">
   ...
</form>

이제 제출 기능에 유형을 추가할 수 있습니다.

onSubmit(userForm: UserFormValue) {
   ...
}

완벽하지는 않지만 제 사용 사례에는 충분했습니다.정말 이런 게 있었으면 좋겠어요.

userForm: FormGroup<UserFormValue>

14 Angular 14)에서 엄격하게 할 수 .next채널)!

FormGroup그리고.FormArray클래스는 내부 컨트롤의 유형인 제네릭을 허용합니다.FormControl클래스는 해당 값 유형의 제네릭을 허용합니다.또한 새로운 클래스가 있습니다.FormRecord컨트롤의 동적 그룹에 사용할 수 있습니다.

다음은 예입니다.

const party = new FormGroup({
  address: new FormGroup({
    house: new FormControl(123, {initialValueIsDefault: true}),
    street: new FormControl('Powell St', {initialValueIsDefault: true}),
  }),
  formal: new FormControl(true),
  foodOptions: new FormArray([
    new FormControl('Soup'),
  ])
});

// whichHouse has type `number`
const whichHouse = party.get('address.house')!.value;

// Error: control "music" does not exist
const band = party.controls.music;

결국 사용하게 된 솔루션은 ngx-strong-type-forms라는 라이브러리였습니다.

FormControls, FormGroups 및 FormArrays를 강력하게 입력할 수 있습니다.몇 가지 한계가 있지만 제 프로젝트에 많은 도움이 되었습니다.

설명서는 https://github.com/no0x9d/ngx-strongly-typed-forms 에서 확인할 수 있습니다.

다음과 할 수 .
**s.ts

export type TCreateUserFields = {
    first_name: string,
    last_name: string,
    accept_terms: boolean,
};
export type TPasswordsControls = {
    passwords: FormGroup & {
        password: AbstractControl,
        confirm_password: AbstractControl
    }
}
export type TPasswordsFields = {
    passwords: {
        password: string,
        confirm_password: string
    }
}
export type TAllFields = TCreateUserFields & TPasswordsFields;
export type TAllControls = TCreateUserControls & TPasswordsControls;
export type TCreateUserControls = {
    [key in keyof TCreateUserFields]: AbstractControl
};
export type TCreateUserFormGroup = FormGroup & {value: TAllFields, controls: TAllControls};

**component.ts
this.registerationForm = this.fb.group(
{
    first_name: new FormControl("", [Validators.required]),
    last_name: new FormControl("", [Validators.required]),
    accept_terms: new FormControl(false, [Validators.required]),
    passwords: new FormGroup(
        {
            password: new FormControl("", [Validators.required, Validators.pattern(/^[~`!@#$%^&*()_+=[\]\{}|;':",.\/<>?a-zA-Z0-9-]+$/)]),
            confirm_password: new FormControl("", [Validators.required, Validators.pattern(/^[~`!@#$%^&*()_+=[\]\{}|;':",.\/<>?a-zA-Z0-9-]+$/)]),
        }, { 
            validators: <ValidatorFn>pwdConfirming({key:'password', confirmationKey:'confirm_password'})
        }
    )
} as TCreateUserControls) as TCreateUserFormGroup;

양식.ts

import { FormControl, FormGroup } from '@angular/forms';

export type ModelFormGroup<T> = FormGroup<{
  [K in keyof T]: FormControl<T[K] | null>;
}>;

login.ts

export interface Ilogin {
  username: string;
  password: string;
}

login.component.ts

loginForm!: ModelFormGroup<Ilogin>;

constructor() {
    this.loginForm = new FormGroup({
      username: new FormControl<string | null>(null, Validators.required),
      password: new FormControl<string | null>(null, Validators.required),
    });
}

Angular 14부터 반응형은 기본적으로 엄격하게 입력됩니다.

https://angular.io/guide/typed-forms

interface LoginForm {
    email: FormControl<string>;
    password: FormControl<string>;
}

const login = new FormGroup<LoginForm>({
    email: new FormControl('', {nonNullable: true}),
    password: new FormControl('', {nonNullable: true}),
});

언급URL : https://stackoverflow.com/questions/55053466/angular-strongly-typed-reactive-forms

반응형