我是 Angular 的新手,正在学习使用 Angular 10 的在线课程,但有一次卡住了。我正在尝试实施反应式表单。
为此,我添加了一个新组件 text-input。 text-input.component.ts
的代码如下:
import { Component, Input, Self } from '@angular/core';
import { ControlValueAccessor, NgControl } from '@angular/forms';
@Component({
selector: 'app-text-input',
templateUrl: './text-input.component.html',
styleUrls: ['./text-input.component.css']
})
// We need to implement a control value accessor
export class TextInputComponent implements ControlValueAccessor {
@Input() label: string;
@Input() type = 'text';
constructor(@Self() public ngControl: NgControl) {
this.ngControl.valueAccessor = this;
}
writeValue(obj: any): void {
}
registerOnChange(fn: any): void {
}
registerOnTouched(fn: any): void {
}
}
这是text-input.component.html
的代码
<div class="form-group">
<input [class.is-invalid]="ngControl.touched && ngControl.invalid" type="{{type}}"
class="form-control"
[formControl]="ngControl.control" placeholder="{{label}}">
<div *ngIf='ngControl.control.errors?.required' class="invalid-feedback">Please enter a {{label}}</div>
<div *ngIf='ngControl.control.errors?.minlength'
class="invalid-feedback">{{label}} must be at least {{ngControl.control.errors.minlength['requiredLength']}}</div>
<div *ngIf='ngControl.control.errors?.maxlength' class="invalid-feedback">{{label}} must be at most {{ngControl.control.errors.maxlength['requiredLength']}}</div>
<div *ngIf='ngControl.control.errors?.isMatching' class="invalid-feedback">
Password do not match</div>
</div>
但是一旦我添加了代码 [formControl]
,我就开始收到错误消息:
Type 'AbstractControl' is missing the following properties from type 'FormControl': registerOnChange, registerOnDisabledChange, _applyFormState
4 [formControl]="ngControl.control" placeholder="{{label}}">
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/app/_forms/text-input/text-input.component.ts:6:16
6 templateUrl: './text-input.component.html',
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component TextInputComponent.
课程讲师正在尝试使用此组件在寄存器组件内生成输入控件,register.component.html
中的代码如下所示
<form [formGroup]="registerForm" (ngSubmit)="register()" autocomplete="off">
<h2 class="text-center text-primary">Sign up</h2>
<hr>
<app-text-input [formControl]='registerForm.controls["username"]' [label]='"Username"'></app-text-input>
<div class="form-group text-center">
<button class="btn btn-dark mr-2" type="submit">Register</button>
<button class="btn btn-success mr-2" (click)="cancel()" type="button">Cancel</button>
</div>
</form>
还有一瞥register.component.ts
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { AbstractControl, FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
import { ToastrService } from 'ngx-toastr';
import { AccountService } from '../_services/account.service';
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit {
@Output() cancelRegister = new EventEmitter();
model: any = {};
registerForm: FormGroup;
constructor(private accountService: AccountService, private toastr: ToastrService, private fb: FormBuilder) { }
ngOnInit(): void {
this.intitializeForm();
}
intitializeForm() {
this.registerForm = this.fb.group({
username: ['', Validators.required]
})
}
register = () => {
console.log(this.registerForm.value);
}
}
请让我知道您还需要什么,我是 Angular 的新手,我无法找到路线原因,但如果您能帮我解决,那么我将继续我的课程,并且非常感谢。
答案 0 :(得分:4)
您是否在此处以严格模式使用 Angular 11?如果是这样,请更改您的 tsconfig.json 文件并设置:
"strictTemplates": false
并忽略“某些语言功能不可用”的错误。
答案 1 :(得分:1)
这是“演员表”的问题。你可以创建一个 getter(当我们管理一个 FormArray 时非常相似,我们创建一个 getter 来转换一个 FormArray)
get control(){
return this.ngControl.control as FormControl
}
并在您的 .html 中将所有 ngControl.control
替换为 control
答案 2 :(得分:1)
这里有多种建议可以将您的 AbstractControl
转换为 FormControl
。您还可以使用例如替换模板中的引用[formControl]="$any(ngControl.control)"
。 $any()
cast operator 是我目前为模板引擎找到的唯一内置转换运算符。
如果这让您感到困扰,请投票并订阅 this extremely popular, longstanding issue,这实际上可以提供一个不错的解决方案。
答案 3 :(得分:1)
我遇到了这个问题,我注意到将 form['controls'] 转换为 FormControl 存在问题,这是因为 form['controls'] 是 AbstractControls 类型。这是我在您的代码中实现的解决方案。 text-input.component.ts
import { Component, Input, Self } from '@angular/core';
import { ControlValueAccessor, NgControl, AbstractControl } from '@angular/forms';
@Component({
selector: 'app-text-input',
templateUrl: './text-input.component.html',
styleUrls: ['./text-input.component.css']
})
// We need to implement a control value accessor
export class TextInputComponent implements OnInit {
@Input() label: string;
@Input() type = 'text';
@Input() abstractcontrol!: AbstractControl;
ngControl!: NgControl;
constructor() {}
ngOnInit(): void {
this.control = this.abstractcontrol as NgControl;
}
}
register.component.html
<form [formGroup]="registerForm" (ngSubmit)="register()" autocomplete="off">
<h2 class="text-center text-primary">Sign up</h2>
<hr>
<app-text-input [abstractcontrol]='registerForm.controls["username"]' [label]='"Username"'></app-text-input>
<div class="form-group text-center">
<button class="btn btn-dark mr-2" type="submit">Register</button>
<button class="btn btn-success mr-2" (click)="cancel()" type="button">Cancel</button>
</div>
</form>
我也是 Angular 的新手。请随时指出我的解决方案中的任何问题。
答案 4 :(得分:0)
在您的自定义响应式表单控件中,您可能需要为组件元数据添加提供程序。
@Component({
selector: 'app-text-input',
templateUrl: './text-input.component.html',
styleUrls: ['./text-input.component.css'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TextInputComponent),
multi: true,
},
]
})
答案 5 :(得分:0)
将控制参数的类型从AbstractControl
替换为Control