首页 > 解决方案 > Angular 元素作为反应形式的原生表单控件

问题描述

我正在尝试将表单控件导出为 Angular 元素(Web 组件)并将其用作本机输入元素,以便它可以与角反应式表单或与本机 html 输入一起使用的类似库一起使用。

波纹管代码在作为模块中的角度组件导出时有效。当我将其导出为 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 错误:表单控件没有值访问器,名称为:'text'

有没有更好的方法来构造这个组件,使其表现得更像原生输入?

标签: angularangular-elements

解决方案


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

所以代码将是:

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

** 编辑 **

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


推荐阅读