我创建了一个BaseInputComponent
实现ControlValueAccessor
的组件。
然后创建一个组件QuickReplyButtonComponent
,该组件在BaseInputComponent
组件上方延伸。
然后,我将QuickReplyButtonComponent
用作AppComponent
中的表单控件。
但是我遇到了错误:
下面的事件代码。
错误:
AppComponent.html:4 ERROR Error: StaticInjectorError(AppModule)[InjectionToken NgValueAccessor -> BaseInputComponent]:
StaticInjectorError(Platform: core)[InjectionToken NgValueAccessor -> BaseInputComponent]:
NullInjectorError: No provider for BaseInputComponent!
at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:8896)
at resolveToken (core.js:9141)
at tryResolveToken (core.js:9085)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:8982)
at resolveToken (core.js:9141)
at tryResolveToken (core.js:9085)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:8982)
at resolveNgModuleDep (core.js:21218)
at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (core.js:21907)
at resolveDep (core.js:22278)
BaseInputComponent:
import {ChangeDetectorRef, Component, Injector, Input, Type} from '@angular/core';
import {ControlValueAccessor} from '@angular/forms';
@Component({
selector: 'app-base',
template: ' '
})
export class BaseInputComponent<T = any> implements ControlValueAccessor {
// @Input()
// cid: string = uuid();
@Input()
disabled: boolean;
@Input()
set value(value: T) {
this._value = value;
this.notifyValueChange();
}
get value(): T {
return this._value;
}
onChange: (value: T) => {};
onTouched: () => {};
protected _value: T;
protected cdRef: ChangeDetectorRef;
constructor(public injector: Injector) {
this.cdRef = injector.get<ChangeDetectorRef>(ChangeDetectorRef as Type<ChangeDetectorRef>);
}
notifyValueChange(): void {
if (this.onChange) {
this.onChange(this.value);
}
}
writeValue(value: T): void {
this._value = value;
setTimeout(() => this.cdRef.detectChanges(), 0);
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
}
}
QuickReplyButtonComponent:
import {Component, forwardRef, OnInit} from '@angular/core';
import {NG_VALUE_ACCESSOR} from '@angular/forms';
import {BaseInputComponent} from './base-input/base-input.component';
@Component({
selector: 'app-quick-reply-button',
template: `
<input type="text" [ngModel]="value">
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => BaseInputComponent),
multi: true,
},
]
})
export class QuickReplyButtonComponent extends BaseInputComponent implements OnInit {
ngOnInit() {
}
updateButton($event, index) {
}
}
AppComponent:
import {ChangeDetectionStrategy, Component, DoCheck, OnInit} from '@angular/core';
import {FormArray, FormBuilder, FormControl, FormGroup} from '@angular/forms';
@Component({
selector: 'app-root',
template: `
<i>test</i>
<form [formGroup]="form">
<app-quick-reply-button formControlName="name"></app-quick-reply-button>
</form>
`,
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor(private formBuilder: FormBuilder) {
}
form: FormGroup;
ngOnInit(): void {
this.form = this.createTestForm();
}
createTestForm() {
return this.formBuilder.group({
name: 'test name',
});
}
}
AppModule:
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {AppComponent} from './app.component';
import {RouterModule} from '@angular/router';
import {TodosComponent} from './todos.component';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {QuickReplyButtonComponent} from './test-input.component';
import {BaseInputComponent} from './base-input/base-input.component';
@NgModule({
declarations: [
AppComponent,
TodosComponent,
QuickReplyButtonComponent,
BaseInputComponent
// BaseInputComponent,
],
// entryComponents:[
// BaseInputComponent
// ],
imports: [
BrowserModule,
RouterModule,
FormsModule,
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
}
答案 0 :(得分:1)
这是因为从未创建BaseInputComponent
的实例。尽管QuickReplyButtonComponent
扩展了BaseInputComponent
,但是角度依存注入无法那样工作。您可以执行以下任一操作
1-更改
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => BaseInputComponent),
multi: true,
}]
到
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: QuickReplyButtonComponent,
multi: true,
}]
2-首先提供BaseInputComponent
,并保留您的NG_VALUE_ACCESSOR
提供者。
providers: [{
provide: BaseInputComponent,
useExisting: QuickReplyButtonComponent,
multi: true,
}, {
provide: NG_VALUE_ACCESSOR,
useExisting: BaseInputComponent,
multi: true,
}]
但是第一个选择是更清洁。