Задать вопрос
@VladimirAl

Как я могу вынести в Angular formControl в отдельный компонент чтобы он был виден в formGroup?

Пытаюсь вынести повторяющееся поле ввода пароля в компонент для его переиспользования, но когда его подключаю к форме, то есть несколько типов ошибок которые я получаю в зависимости от того каким путем пытаюсь подключить инпут к форме.
Первая ошибка - ERROR Error: No value accessor for form control with name: 'password', когда я передаю с компонента формы в компонент пароля через директиву @Input этот контрол:

<app-password-field
  [formCtrl]="form.get('password')"
></app-password-field>

Дочерний компонент получает контрол:

@Input() formCtrl!: FormControl
и используется в шаблоне:

<input
  matInput
  [type]="isPasswordHidden ? 'password' : 'text'"
  [name]="name"
  [formControl]="formCtrl"
/>


Вторая ошибка у меня получается после того как я проворачиваю эти манипуляции. Выглядит она следующим образом:
error TS2739: Type 'AbstractControl' is missing the following properties from type 'FormControl'

login.component.html

<app-welcome-form>
  <form class="container" (submit)="userLoginClick()" [formGroup]="form">
    <app-password-field
      titleOfField="Enter your password"
      hintLabel="Use at least 6 symbols"
      name="password"
      formControlName="password"
      [formCtrl]="$any(passwordInput)"
    ></app-password-field>
    <mat-form-field appearance="fill">
      <mat-label>Username</mat-label>
      <input
        matInput
        #input
        placeholder="Username"
        name="username"
        formControlName="username"
      />
    </mat-form-field>

    <button mat-raised-button color="primary">Sign in</button>
  </form>

  <p class="is-member">Not a member yet?</p>
  <a routerLink="/signup">Sign up</a>
</app-welcome-form>


login.component.ts

import { Component, Input, OnInit } from '@angular/core';
import { FormValidationService } from 'src/app/form-validation.service';
import { AuthService } from '../../auth.service';
import { Router } from '@angular/router';
import {
  AbstractControl,
  FormBuilder,
  FormControl,
  FormGroup,
  Validators,
} from '@angular/forms';
import { MatSnackBar } from '@angular/material/snack-bar';

@Component({
  selector: 'app-autorization',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss'],
})
export class LoginComponent implements OnInit {
  isPasswordHidden = true;
  form!: FormGroup;
  public passwordInput!: AbstractControl;

  constructor(
    private formValidationService: FormValidationService,
    private router: Router,
    private authService: AuthService,
    private fb: FormBuilder,
    private snackbar: MatSnackBar
  ) {}

  ngOnInit(): void {
    this.form = this.fb.group({
      username: ['', [Validators.required, Validators.minLength(3)]],
      password: ['', [Validators.required, Validators.minLength(6)]],
    });
    this.passwordInput = this.form.controls['password'];
  }

  userLoginClick() {
    if (!this.form.valid) {
      this.snackbar.open('Data format is incorrect', 'X', {
        duration: 2000,
        horizontalPosition: 'center',
        verticalPosition: 'top',
      });
      return false;
    }
    const user = {
      username: this.form.controls['username'].value,
      password: this.form.controls['password'].value,
    };

    this.authService.authUser(user);
  }
  togglePassVisibility(e: Event) {
    e.preventDefault();
    this.isPasswordHidden = !this.isPasswordHidden;
  }
}


pass.component.html

<mat-form-field appearance="fill" hintLabel="{{ hintLabel }}">
  <mat-label>{{ titleOfField }}</mat-label>
  <input
    matInput
    [type]="isPasswordHidden ? 'password' : 'text'"
    [name]="name"
    [formControlName]="formControlName"
    [formControl]="formCtrl"
  />
  <button
    mat-icon-button
    matSuffix
    (click)="togglePassVisibility($event)"
    [attr.aria-label]="passwordVisibilityStatus"
    [attr.aria-pressed]="isPasswordHidden"
    class="change-visibility"
  >
    <mat-icon>{{
      isPasswordHidden ? "visibility_off" : "visibility"
    }}</mat-icon>
  </button>
</mat-form-field>


pass.component.ts

import { Component, Input, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';

@Component({
  selector: 'app-password-field',
  templateUrl: './password-field.component.html',
  styleUrls: ['./password-field.component.scss'],
})
export class PasswordFieldComponent implements OnInit {
  isPasswordHidden = true;
  passwordVisibilityStatus = 'Hide password';
  @Input() titleOfField!: string;
  @Input() hintLabel!: string;
  @Input() name!: string;
  @Input() formControlName!: string;
  @Input() formCtrl!: FormControl;

  constructor() {}

  ngOnInit(): void {}

  togglePassVisibility(e: Event) {
    e.preventDefault();
    this.isPasswordHidden = !this.isPasswordHidden;
    if (this.passwordVisibilityStatus === 'Hide password') {
      this.passwordVisibilityStatus = 'Show password';
    } else {
      this.passwordVisibilityStatus = 'Hide password';
    }
  }
}
  • Вопрос задан
  • 153 просмотра
Подписаться 1 Средний Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы