我一直在尝试使用 Angular 元素创建自定义元素,对于表单输入,我一直在尝试使用 Angular 的 ControlValueAccessor 来实现这一点,如 Eliran Eliassy 的 this 文章中所讨论的。
但是当我按照指南完成代码时 - 我遇到了这个问题。 没有 NgControl 的提供者。我已经将 FormsModule 和 ReactiveFormsModule 导入到 app.module.ts 文件中,这是此错误的补救措施(正常情况下)。但这次还没修好。
会出现什么问题?我附上了上面的 stackbliz 供您参考。
感谢您在这里发帖,让更多人受益。
你犯了两个错误:
当您注入
NgControl
时,您不必提供NG_VALUE_ACCESSOR
令牌。原因是 NgControl
已经提供了 NG_VALUE_ACCESSOR
令牌,如果您也这样做,您将遇到循环依赖问题。因为您的
TestComponent
是入口组件,所以您还必须在 @Optional()
注入之前添加 NgControl
装饰器。原因是当你在入口组件中声明一个组件时,Angular 会在工厂编译它,即使它不在模板上,并且因为它不属于任何表单,并且上面没有任何 From 指令,所以你会得到以下错误No provider for NgControl
希望有帮助!
您的 AppModule 和 DoBootstrap 实现有问题。如果您删除它并另外从 appModule 中的 entryComponents 中删除您的组件并更改它在 app-component.html 中的使用方式,一切似乎都工作正常。
app.module.ts
@NgModule({
imports: [BrowserModule, FormsModule, ReactiveFormsModule],
declarations: [AppComponent, HelloComponent, TestInputComponent],
bootstrap: [AppComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule {
constructor(private injector: Injector) {
}
}
app.component.html
<form class="form-signin" (ngSubmit)="onSubmit(f.value)" #f="ngForm" >
<app-test-input [placeholder]="'Email'"
[isRequired]="true"
[errorMsg]="'Please enter your name'"
[label] = "'User Email'"
[pattern]="'[A-Za-z0-9._%-]+@[A-Za-z0-9._%-]+\\.[a-z]{2,3}'"
ngModel name="email"></app-test-input>
<button class="btn btn-lg btn-primary btn-block" [disabled]="!f.valid" type="submit">Sign in</button>
</form>
找到解决方案。
通过将 ngDefaultControl 添加为自定义元素中的指令并手动实现 ControlValueAccessor 部分来修复错误。
这是一个实现示例(不要介意验证部分,尚未完成) 堆栈闪电战
请关注这些问题以获取更多信息。
从你的 app.module.ts 中删除这一行
entryComponents: [TestInputComponent]
您还从 app.module.ts 中删除了 DoBootstrap 实现 并将 ust-input 替换为 app-test-input ,它将起作用。同时删除
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: TestInputComponent,
multi: true
}]
因为它会产生循环依赖。
对于其他收到此错误的人来说,就我而言,问题是缺少 formControlName 属性和缺少 formGroup 作为父级。如果您也在项目中使用自定义表单控件,请确保所有引用 - formControlName 和 [formGroup]="myFormGroup" - 均已正确设置。
在您的
NgControl
中提供 TestingModule
,如下所示:
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ ... ReactiveFormsModule, FormsModule ... ],
declarations: [
...Component,
],
providers: [NgControl], // <-- this
});
fixture = TestBed.createComponent(...Component);
component = fixture.componentInstance;
fixture.detectChanges();
});