没有 ngModel 的反应式表单中的自定义输入文本



我的自定义文本输入:

import { Component, Inject, Injector, Input, Optional, ViewChild, Output, 
EventEmitter } from '@angular/core';
import { NG_VALUE_ACCESSOR, NgModel } from '@angular/forms';
import { ValueAccessorBase } from '../base-elements/value-accessor';
@Component({
selector: 'sm-input',
templateUrl: './sm-input.component.html',
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: SmInputComponent,
multi: true,
}],
styleUrls: ['./sm-input.component.scss'],
})
export class SmInputComponent extends ValueAccessorBase<string> {
constructor(injector: Injector) {
super(injector);
} 
} 

SM-input HTML:(我删除了不必要的内容)

<div>
<div *ngIf="label">
<label>
{{label}} 
</label>
</div>
<div>
<input  
type="text" 
pInputText
[(ngModel)]="value"
/>
</div>
</div>

我的表格:

import { HttpModule, Http } from '@angular/http';
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
@Component({
selector: 'sm-input-example-in-reactive-from',
templateUrl: './sm-input-example-in-reactive-from.component.html',
styleUrls: ['./sm-input-example-in-reactive-from.component.scss']
})
export class SmInputExampleInReactiveFromComponent {
public firstName: string = "Bob";
myReactiveForm: FormGroup;
constructor(fb: FormBuilder, private http: Http) {
this.myReactiveForm = fb.group ({
myField: [this.firstName, [Validators.required]],
});
}
onSubmit(value) {
console.log(`Submit: ${JSON.stringify(value)}`);
}
}

网页表单

<p-panel header="Reactive Form">
<form action="" [formGroup]="myReactiveForm" (ngSubmit)="onSubmit(myReactiveForm.value)">
<div class="ui-grid-row">
<sm-input
label="First Name"
formControlName="myField">
</sm-input> 
</div>
<div class="ui-grid-row">
<div class="ui-g-2 ui-g-offset-5">
<button type="Submit" class="" pButton [disabled]="!myReactiveForm.valid">Submit</button>
</div> 
</div>
</form>
</p-

在 sm-input HTML 中,我用在 [(ngModel)]="value" 中使用。

它正在工作。但我不想在 [(ngMode)]="value">

因为反应式形式不需要与 ngMode 一起使用。 我读了这篇文章 反应式形式的双向绑定

在驱动形式和反应形式之间混合使用不是一个好主意。

角度文档:https://angular.io/guide/reactive-forms

"...出于这个原因,ngModel 指令不是 ReactiveFormsModule 的一部分"。

我该怎么办?

谢谢。

您正在寻找.setValue()方法。顾名思义,它允许您以编程方式设置反应式表单控件的值。

以下是Angular指南中相关部分的链接:https://angular.io/guide/reactive-forms#populate-the-form-model-with-setvalue-and-patchvalue

这是API中方法的链接:https://angular.io/api/forms/FormControl#setValue


第一种方法(使用BehaviorSubject表示自定义组件上的当前输入值)若要获取自定义输入组件的值,可以在自定义文本输入上生成一个流,该流表示其随时间推移的值。

inputValue$ = new BehaviorSubject('');

并侦听该输入字段上的input事件。

<input (input)="onInputChange($event)">

然后使用输入中的最新值更新inputValue$流。

onInputChange(mostRecentInputValue: string) {
this.inputValue$.next(mostRecentInputValue);
}

现在,您的自定义输入上有一个流,您可以在父级中订阅该流。

最后,在表单组件中,您可以使用@ViewChild装饰器来获取自定义输入组件,从而访问其公共属性(包括inputValue$

@ViewChild('sm-input') myCustomInput: SmInputComponent;
ngAfterViewInit() {
this.myCustomInput.inputValue$.subscribe(mostRecentInput => {
this.myReactiveForm.get('myField').setValue(mostRecentInput);
}
}

第二种方法(使用@Output)

在自定义输入上:

<input (input)="onInputChange($event)">

然后使用带有装饰器的EventEmitter@Output将该更改发送给父级;

@Output inputChange = new EventEmitter<string>();
onInputChange(mostRecentInputValue: string) {
this.inputChange.emit(mostRecentInputValue);
}

然后在您的父 html 中:

<sm-input (inputChange)="onSmInputChange($event)">

和您的组件:

onSmInputChange(recentValue: string) {
this.myReactiveForm.get('myField').setValue(recentValue);
}

求解, 谢谢大家!

自定义文本:

import { Component, Inject, Injector, Input, Optional, ViewChild, Output, 
EventEmitter } from '@angular/core';
import { NG_VALUE_ACCESSOR, NgModel } from '@angular/forms';
import { ValueAccessorBase } from '../base-elements/value-accessor';
@Component({
selector: 'sm-input',
templateUrl: './sm-input.component.html',
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: SmInputComponent,
multi: true,
}],
styleUrls: ['./sm-input.component.scss'],
})
export class SmInputComponent extends ValueAccessorBase<string> {
constructor(injector: Injector) {
super(injector);
} 
doChange($event) {
this.value = $event.target.value;
}
} 

SM-input HTML:

<div>
<div *ngIf="label">
<label>
{{label}} 
</label>
</div>
<div>
<input  
type="text" 
[value]"innerValue"
(change)="doChange($event)"
/>
</div>
</div>

(innerValue 在 ValueAccessorBase 中定义)

谢谢大家!

最新更新