我很头疼想弄清楚这个问题。我想创建一个可以在我的 Angular/Ionic 应用程序中使用的自定义输入元素。我如何将 Angular 属性与这些自定义元素一起使用,例如 FormControlName。
<my-custom-stencil-input type="text" formControlName="firstName"></my-custom-stencil-input>
我有下面的代码,但是当我尝试使用 FormControlName 时它显示错误。
import { Component, h, Prop } from '@stencil/core';
@Component({
tag: 'ba-text-input-one',
styleUrl: './text-input-1.component.css',
scoped: true,
})
export class TextInputOne {
@Prop({reflect: true}) type: string;
@Prop({reflect: true}) placeholder: string;
@Prop({reflect: true}) formControlName: string;
render() {
return (
<div id="cmp">
<div id="icon-area">
<slot name="icon"></slot>
</div>
<input id="input-field" formControlName={this.formControlName} type={this.type} />
</div>
);
}
}
Stencil 上的文档没有详细说明如何解决这个问题。
本质上,我想在 Angular 响应式表单中使用我自己的自定义 Stencil 输入元素。
最佳答案
我遇到了同样的问题,但我找到了解决方案:
首先,您不必在模板项目中创建 formControlName。
import { Component, Event, EventEmitter, h, Prop } from "@stencil/core";
@Component({
tag: 'my-custom-stencil-input',
styleUrl: 'input.css',
shadow: true
})
export class Input {
@Prop({reflect: true, mutable: true}) label: string;
@Prop({reflect: true, mutable: true}) value: string;
@Prop() type = 'text';
@Event() valueChanged: EventEmitter<string>;
private onInputChangeValue(event: Event) {
this.value = (event.target as HTMLInputElement).value;
this.valueChanged.emit(this.value);
}
render() {
return (
<div>
<label> {this.label} </label>
<input type= {this.type} value= {this.value} onInput= {this.onInputChangeValue.bind(this)}/>
</div>
)
}
}
然后,在 Angular 项目中,您必须创建一个指令,因为您需要实现 ControlValueAccessor,它充当 Angular 表单 API 和 DOM 中 native 元素之间的桥梁。
import { Directive, forwardRef, HostBinding, HostListener } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Directive({
selector: '[appAccessor]',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FormDirective),
multi: true,
},
],
})
export class FormDirective implements ControlValueAccessor {
@HostBinding('value') hostValue: any;
lastValue: any;
private onChange = (value: any) => {};
private onTouched = () => {};
writeValue(value: any) {
this.hostValue = this.lastValue = value == null ? '' : value;
}
registerOnChange(fn: (value: any) => void) {
this.onChange = fn;
}
registerOnTouched(fn: () => void) {
this.onTouched = fn;
}
@HostListener('valueChanged', ['$event.detail'])
_handleInputEvent(value: any) {
if (JSON.stringify(value) !== JSON.stringify(this.lastValue)) {
this.lastValue = value;
this.onChange(value);
this.onTouched();
}
}
}
最后,以 react 形式使用自定义元素(在本例中为输入):
<form [formGroup]="myFormGroup">
<my-custom-stencil-input label="Any label" appAccessor formControlName="control1" ></my-custom-stencil-input>
</form>
就是这样。
关于angular - 如何在 Stencil 中创建自定义输入元素以与 Angular/Ionic 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63909749/