ChatGPT解决这个技术问题 Extra ChatGPT

反应形式的两种方式绑定

使用 Angular 2,在模板驱动的表单中双向绑定很容易——您只需使用香蕉盒语法。您将如何以模型驱动的形式复制这种行为?

例如,这是一个标准的反应形式。让我们假设它比看起来要复杂得多,有很多不同的输入和业务逻辑,因此更适合模型驱动的方法而不是模板驱动的方法。

    export class ExampleModel {
        public name: string;
        // ... lots of other inputs
    }

    @Component({
        template: `
            <form [formGroup]="form">
                <input type="text" formControlName="name">
                ... lots of other inputs
            </form>

            <h4>Example values: {{example | json}}</h4>
        `
    })
    export class ExampleComponent {
        public form: FormGroup;
        public example: ExampleModel = new ExampleModel();

        constructor(private _fb: FormBuilder) {
            this.form = this._fb.group({
                name: [ this.example.name, Validators.required ]
                // lots of other inputs
            });
        }

        this.form.valueChanges.subscribe({
            form => {
                console.info('form values', form);
            }
        });
    }

subscribe() 中,我可以将各种逻辑应用于表单值并根据需要映射它们。但是,我不想映射表单中的每个输入值。我只想查看整个 employee 模型更新时的值,采用类似于 [(ngModel)]="example.name" 的方法,并显示在模板的 json 管道中。我怎样才能做到这一点?

在此处查看正确答案stackoverflow.com/questions/51342775/…

C
Community

注意:正如@Clouse24 所提到的,“Angular 6 中不推荐使用带有 ngModel 的 Reactive Froms,并将在 Angular 的未来版本中删除”(这意味着未来将不再支持下面的答案)。请阅读链接以查看弃用的原因并查看您将拥有哪些替代方案。

您可以将 [(ngModel)] 与响应式表单一起使用。

模板

<form [formGroup]="form">
  <input name="first" formControlName="first" [(ngModel)]="example.first"/>
  <input name="last" formControlName="last" [(ngModel)]="example.last"/>
</form>

零件

export class App {
  form: FormGroup;
  example = { first: "", last: "" };

  constructor(builder: FormBuilder) {
    this.form = builder.group({
      first: "",
      last: ""
    });
  }
}

Plunker

这将是一个完全不同于没有 formControlName 的指令。对于反应形式,它将是 FormControlNameDirective。如果没有 formControlName,将使用 NgModel 指令。


在 Angular/Angular 中问了一个类似的问题,两个核心开发人员告诉我混合使用 ngModel 和 Reactive 表单是个坏主意。您应该能够使用 {{this.form.get('first').value}} 获取值
@Zuriel,但我怎样才能将我的本地模型数据直接绑定到我的表单,以便我的模型数据有两种数据绑定方式?因为没有上述解决方案,我需要将我的表单数据映射回我的模型数据
angular.io/guide/reactive-forms 为了与响应式范式保持一致,组件保留了数据模型的不变性,将其视为原始值的纯粹来源。该组件不是直接更新数据模型,而是提取用户更改并将它们转发到外部组件或服务,后者对它们执行某些操作(例如保存它们)并将新的数据模型返回给反映更新的模型状态的组件。
在 Angular 6 中不推荐将 Reactive Froms 与 ngModel 一起使用,并将在 Angular 7 中删除。angular.io/api/forms/FormControlName#use-with-ngmodel
所以,简而言之:双向绑定不适用于 FormBuilder? (即当formControl值改变时自动更新模型)
J
Jens Alenius

有时您可能需要将 [(ngModel)] 与响应式表单结合使用。我可能是一些你不需要的输入控件作为表单的一部分,但你仍然需要将它绑定到控制器。然后您可以使用:[(ngModel)]="something" [ngModelOptions]="{standalone: true}"


这在 Angular v6 中已被弃用,并将在 Angular v7 中删除。您可以查看此以获取更多详细信息next.angular.io/api/forms/FormControlName#use-with-ngmodel
我很高兴地报告这在 Angular 9 中有效。我希望他们已经改变了主意并会保留这一点。
@N8allan 不,它仍然被弃用,看看你的控制台。 It looks like you're using ngModel on the same form field as formControlName. Support for using the ngModel input property and ngModelChange event with reactive form directives has been deprecated in Angular v6 and will be removed in a future version of Angular.
@Shadoweb,就是这么说的,但我认为他们应该重新考虑。在某些情况下,没有使用绑定来支持表单,并且取消此功能会导致不必要的迂回。像这样的限制就是你所说的非正交的,它们使框架和语言变得不优雅和繁琐。
A
Andre Elrico

以下是您可以解决的方法:

快捷方式 --> STACKBLITZ

为了得到two-way-binding的结果

我使用本地“模板变量”并为两个字段使用相同的 formControl。

<form [formGroup]="formGroup">
  <input #myInput (input)="mySlider.value = myInput.value" type="number" formControlName="twoWayControl">

  <mat-slider #mySlider (input)="myInput.value = mySlider.value" formControlName="twoWayControl" min="1" max="100">
  </mat-slider>

</form>

当我想以编程方式更改模型的值时,我使用 setValue(),正如其他人所宣称的那样。

setTo33() {
  this.formGroup.get('twoWayControl').setValue(33);
}

这对我有用!由于 Angular 7 反应形式不支持 ngModel
对于阅读本文的 Angular 开发人员。我对 ngModel 和 formControlName 并不感到困惑!这实际上非常方便,制作了一个响应式表单并绑定了一个模型。如果我们可以同时做两件事呢?像这样:formGroup = new FormGroup({ name: new FormControl(['Michelangelo', {modelBinding: true}]) }) 所以我们实际上可以将它绑定到模型而不是手动更新它。
T
Thomas Leo Blok
    // Allow two way binding on the [(name)] from the parent component
    private nameValue: string;
    @Input()
    get name() {
        return this.nameValue;
    }
    set name(values) {
        this.nameValue = values;
        this.nameChange.emit(this.nameValue);
    }
    @Output() nameChange = new EventEmitter<string>();

    ngOnInit() {
        // Update local value and notify parent on control value change
        this.formControl.valueChanges.forEach(value => this.name = value));
    }

    ngOnChanges() {
        // Update local value on parent change
        this.formControl.setValue(this.expression);
    }

k
kneeki

Angular 6+ 解决方案...

我也希望在使用双向数据绑定的同时进行反应式表单验证。我想出的最佳解决方案是将表单组的 valueChanges 事件与 debounce 计时器挂钩以更新模型。这是一个例子:

<form [formGroup]="form">
  <input class="form-control" type="date" name="myDate" formControlName="myDate">
</form>
public myModel = {
  myDate: '2021-01-27'
};

public form = this.builder.group({
  myDate: [this.myModel.myDate, [Validators.required]],
});

// Don't update the model with every keypress, instead wait 1s and then update
this.form.valueChanges.pipe(debounceTime(1000)).subscribe((changes) => {
  for (let key of Object.keys(changes)) {
    this.myModel[key] = values[key];
  }
});

为了更好地帮助复制/意大利面,我将使用给定的更改更新穆德尔所有属性的值。如果你只想用双向数据绑定更新一个属性,你应该使用类似的东西:

this.form.get('myDate').valueChanges.pipe(debounceTime(1000)).subscribe((changes) => {
  this.myModel.myDate = changes.myDate;
});

我真的很喜欢这个。我只是想知道为什么更新模型不像模板驱动的表单那样自动?似乎他们不希望我们不这样做,否则默认情况下会发生。他们经常指出我们将响应式表单作为最佳实践而不是模板驱动的表单,并强调他们不希望我们这样做。另外从响应式表单中删除 ngModel。我阅读了弃用文档,其中说这是因为它令人困惑。但这对我来说似乎更方便。
T
Thomas Leo Blok

如果您只想显示输入值,只需在输入中创建一个变量并在模板中使用。

<form [formGroup]="form">
  <input type="text" formControlName="name" #name>
  ... lots of other inputs
</form>

<h4>Example values: {{ name.value }}</h4>

澄清一下,这种技术是对 FormControl 本身的纯绑定,而不是对模型的绑定。
A
Alexander Gharibashvili

ngModel 或模板驱动表单和响应式表单(模型驱动表单)可以混合在一起。例如,当您使用 TDF 时,无需订阅即可轻松读取数据,另一方面,您可以使用 MDF 提供一些验证。但我宁愿只选择其中之一。

TDF 的最大缺点是您不能对它们应用单元测试,另一方面,当您使用 TDF 时模板更加脏。


E
Eamanpreet Singh

您可以使用反应式表单实现两种方式绑定

constructor(private fb: FormBuilder) this.formData= fb.group({ variable: new FormControl(value,Validators.required) }) //'value'属性携带你要绑定的值 var value="Eamanpreet Singh"


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅