【问题标题】:custom input text inside reactive form without ngModel没有ngModel的反应形式内的自定义输入文本
【发布时间】:2018-01-25 18:07:19
【问题描述】:

我的自定义文本输入:

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 输入 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)}`);
  }
}

html 表单

<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-

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

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

因为响应式表单不需要使用 ngMode。 我读了这篇文章 Two way binding in reactive forms

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

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

"...因此,ngModel 指令不属于 ReactiveFormsModule"。

我该怎么办?

谢谢。

【问题讨论】:

  • 你有什么问题?如果您不想使用 ngModel,请不要使用它。
  • 您似乎了解数据绑定,您在示例中使用了它,因此只需在输入值或您需要的任何地方再次使用它...
  • “所以只需在输入值或任何你需要的地方再次使用它”。我需要将 formControler (firstName) 绑定到我的自定义组件。在主机组件(表单)中,我创建了自定义组件(sm-input)的实例,其中 formControlName 绑定到 form.ts 中的 firstName。如何在没有 [(ngModel)] 的情况下将 formControler (firstName) 绑定到我的自定义输入组件。

标签: angular textinput angular-reactive-forms two-way-binding


【解决方案1】:

您正在寻找.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);
}

【讨论】:

  • 谢谢,我知道'setValue'和'patchValue'。但这仍然不是解决方案。如何将我的 fromGroup 中的“formControl”(名字)绑定到自定义输入文本组件(sm-input)。
  • 更新了我的答案
【解决方案2】:

已解决, 谢谢大家!

自定义文本:

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>

(在ValueAccessorBase中定义的innerValue)

谢谢大家!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 2017-03-03
    • 2019-11-26
    • 1970-01-01
    • 2018-12-01
    • 1970-01-01
    • 2021-10-20
    相关资源
    最近更新 更多