使用Angular元素作为响应式表单中的原生表单控件

6
我想将一个表单控件作为Angular Element(Web组件)导出,并将其作为本地输入元素运行,以便可与Angular响应式表单或类似使用本机HTML输入的库一起使用。
以下代码在导出为Angular模块中的组件时有效。当我将其导出为Web组件并尝试在响应式表单中使用它时,出现了问题。
此代码是使用Angular 7.1框架编写的。
组件模板:
<input ngDefaultControl value="value" />

组件代码:
@Component({
  selector: 'cns-text-input',
  templateUrl: './text-input.component.html',
  styleUrls: ['./text-input.component.scss'],
  providers: [ {
    provide: NG_VALUE_ACCESSOR,
    useExisting:  forwardRef(() => TextInputComponent),
    multi: true
  }]
})
export class TextInputComponent implements ControlValueAccessor,     AfterViewInit {

  @ViewChild(DefaultValueAccessor) valueAccessor:     DefaultValueAccessor;

  public ngAfterViewInit() {
    console.log('value accessor', this.valueAccessor);
    console.log(this);
  }

  public writeValue(obj: any): void {
    this.valueAccessor.writeValue(obj);
  }
  public registerOnChange(fn: any): void {
    this.valueAccessor.registerOnChange(fn);
  }
  public registerOnTouched(fn: any): void {
    this.valueAccessor.registerOnTouched(fn);
  }
  public setDisabledState?(isDisabled: boolean): void {
    this.valueAccessor.setDisabledState(isDisabled);
  }

}

模块代码:

@NgModule({
  declarations: [TextInputComponent],
  imports: [FormsModule],
  // exports: [TextInputComponent],
  entryComponents: [TextInputComponent]
})
export class FormModule {
  constructor(private injector: Injector) {
    const textInputElement = createCustomElement(TextInputComponent, { 
      injector 
    });
    customElements.define('cns-text-input', textInputElement);
  }

  ngDoBootstrap() {}
}

使用示例:

// app component html
<form [formGroup]="group">
  <cns-text-input formControlName="text"></cns-text-input>
</form>

// app component

export class AppComponent {
  title = 'web-components-lib-poc';

  public group: FormGroup;

  constructor(private fb: FormBuilder) {
    this.group = this.fb.group({ text: 'my vlaue' });
    this.group.valueChanges.subscribe(val => console.log(val));
  }
}

上述代码会导致错误:ERROR Error: No value accessor for form control with name: 'text'

有没有更好的构造该组件的方法,使其更像本地输入框?

1个回答

8
我找到了答案。在使用非本地输入组件时,ngDefaultControl将有助于解决值访问器错误的问题。

因此,代码应该是:

<cns-text-input formControlName="text" ngDefaultControl></cns-text-input>

** 编辑 **

这也适用于其他 Web 组件,例如 Polymer Elements Paper Input。


1
请问您能否将您的代码添加到 Stack-blitz 中?我有相同的代码,但它对我不起作用! - Elham abbasi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接