Пытаюсь вынести повторяющееся поле ввода пароля в компонент для его переиспользования, но когда его подключаю к форме, то есть несколько типов ошибок которые я получаю в зависимости от того каким путем пытаюсь подключить инпут к форме.
Первая ошибка - 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';
}
}
}