从组件更改模型时未调用 ngModelChange
ngModelChange not called when changing the model from component
我是 Angular 的新手,我正在尝试了解如何连接不同的控制器,以便在控制器发生变化时更改控制器的值。
在这种特殊情况下,我有一个带有 ngModel 的表单,并尝试使用 ngModelChange 更新我模型中其他 属性 的值,问题是当用户与控件交互时调用 ngModelChange , 但在从组件更新模型时未被调用。
让我给你看一个示例代码。
https://stackblitz.com/edit/angular-ivy-z2q4mr
HTML 模板:
<form #f="ngForm" (ngSubmit)="onSubmit(f)">
<mat-form-field appearance="fill">
<mat-label>Field 1</mat-label>
<input matInput name="field1" [(ngModel)]="MyItem.field1" (ngModelChange)="changeField2($event)">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Field 2</mat-label>
<input matInput disabled name="field2" [(ngModel)]="MyItem.field2" (ngModelChange)="changeField3($event)">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Field 3</mat-label>
<input matInput disabled name="field3" [(ngModel)]="MyItem.field3">
</mat-form-field>
</form>
组件
import { OnInit, Component, ViewChild } from '@angular/core';
@Component({
selector: 'app-component1',
templateUrl: './component1.component.html',
styleUrls: ['./component1.component.css']
})
export class Component1Component implements OnInit {
MyItem : any = {}
constructor() {
}
ngOnInit(): void {
}
changeField2(event: any){
this.MyItem.field2 = this.MyItem.field1 + " modification field 2"; //We can see that everytime field1 is changed is updating field2
}
changeField3(event: any) {
this.MyItem.field3 = this.MyItem.field2 + " modification field 3"; //Eventhough we are updating field2, this is not being called
}
}
如果我更改了 field1(因为它与 field2 相关),我希望 field3 会自动更新。当然,我考虑过在 changeField2
上调用 changeField3
,但是如果我有一个包含很多控制器的表单,这太混乱了,可以从不同的方法调用相同的操作。
Field3
不会更新,因为您没有在 Field2
中输入任何内容。
(ngModelChange) is the @Output of ngModel directive. It fires when
the model changes.
为了使您的示例正常工作,您必须在第一个字段发生变化时同时改变第三个字段和第二个字段
changeField2(event: any) {
this.MyItem.field2 = this.MyItem.field1 + ' modification field 2';
this.MyItem.field3 = this.MyItem.field2 + ' modification field 3';
}
另一种实现你想要的方法是使用ReactiveForms
Playground
在这种情况下,您可以在 HTML
中的表单标记中使用 (change)
<form #f="ngForm" (change)="changeField3()">
<mat-form-field appearance="fill">
<mat-label>Field 1</mat-label>
<input matInput name="field1" [(ngModel)]="MyItem.field1" (ngModelChange)="changeField2($event)">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Field 2</mat-label>
<input matInput disabled name="field2" [(ngModel)]="MyItem.field2" >
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Field 3</mat-label>
<input matInput disabled name="field3" [(ngModel)]="MyItem.field3">
</mat-form-field>
</form>
并在 Ts
changeField3() {
this.MyItem.field3 = this.MyItem.field2 + ' modification field 3';
}
这种方法会监听表单模型中的每一个变化
我能够使用反应形式和 属性 ValueChanges
来做我需要的事情来捕捉控制器值何时发生变化。即使组件中的方法更改了控制器值,也会执行此操作。
这里有使用反应形式的相同示例:
https://stackblitz.com/edit/angular-ivy-gh7zho
HTML 模板:
<form [formGroup]="testForm" (ngSubmit)="onSubmit()">
<mat-form-field appearance="fill">
<mat-label>Field 1</mat-label>
<input matInput name="field1" formControlName="field1" />
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Field 2</mat-label>
<input matInput name="field2" formControlName="field2" />
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Field 3</mat-label>
<input matInput name="field3" formControlName="field3" />
</mat-form-field>
<button type="submit">Submit</button>
</form>
<button (click)="resetField2()">Reset field2</button>
组件
import { OnInit, Component, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Validators } from '@angular/forms';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
testForm: FormGroup = this.fb.group({
field1: [{ value: '', disabled: false }, Validators.required],
field2: [{ value: '', disabled: true }, Validators.required],
field3: [{ value: '', disabled: true }, Validators.required]
});
constructor(private fb: FormBuilder) {
const field1 = this.testForm.get('field1');
const field2 = this.testForm.get('field2');
field1!.valueChanges.subscribe(val => {
this.changeField2();
});
field2!.valueChanges.subscribe(val => {
this.changeField3();
});
}
changeField2() {
this.testForm
.get('field2')!
.setValue(this.testForm.get('field1')!.value + ' modification field 2'); //We can see that everytime field1 is changed is updating field2
}
changeField3() {
this.testForm
.get('field3')!
.setValue(this.testForm.get('field2')!.value + ' modification field 3'); //Eventhough we are updating field2, this is not being called
}
resetField2() {
this.testForm.get('field2')!.setValue(''); //This should leave field2 with only modification field 3
}
onSubmit() {
console.warn(this.testForm.value);
}
}
我是 Angular 的新手,我正在尝试了解如何连接不同的控制器,以便在控制器发生变化时更改控制器的值。
在这种特殊情况下,我有一个带有 ngModel 的表单,并尝试使用 ngModelChange 更新我模型中其他 属性 的值,问题是当用户与控件交互时调用 ngModelChange , 但在从组件更新模型时未被调用。
让我给你看一个示例代码。
https://stackblitz.com/edit/angular-ivy-z2q4mr
HTML 模板:
<form #f="ngForm" (ngSubmit)="onSubmit(f)">
<mat-form-field appearance="fill">
<mat-label>Field 1</mat-label>
<input matInput name="field1" [(ngModel)]="MyItem.field1" (ngModelChange)="changeField2($event)">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Field 2</mat-label>
<input matInput disabled name="field2" [(ngModel)]="MyItem.field2" (ngModelChange)="changeField3($event)">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Field 3</mat-label>
<input matInput disabled name="field3" [(ngModel)]="MyItem.field3">
</mat-form-field>
</form>
组件
import { OnInit, Component, ViewChild } from '@angular/core';
@Component({
selector: 'app-component1',
templateUrl: './component1.component.html',
styleUrls: ['./component1.component.css']
})
export class Component1Component implements OnInit {
MyItem : any = {}
constructor() {
}
ngOnInit(): void {
}
changeField2(event: any){
this.MyItem.field2 = this.MyItem.field1 + " modification field 2"; //We can see that everytime field1 is changed is updating field2
}
changeField3(event: any) {
this.MyItem.field3 = this.MyItem.field2 + " modification field 3"; //Eventhough we are updating field2, this is not being called
}
}
如果我更改了 field1(因为它与 field2 相关),我希望 field3 会自动更新。当然,我考虑过在 changeField2
上调用 changeField3
,但是如果我有一个包含很多控制器的表单,这太混乱了,可以从不同的方法调用相同的操作。
Field3
不会更新,因为您没有在 Field2
中输入任何内容。
(ngModelChange) is the @Output of ngModel directive. It fires when the model changes.
为了使您的示例正常工作,您必须在第一个字段发生变化时同时改变第三个字段和第二个字段
changeField2(event: any) {
this.MyItem.field2 = this.MyItem.field1 + ' modification field 2';
this.MyItem.field3 = this.MyItem.field2 + ' modification field 3';
}
另一种实现你想要的方法是使用ReactiveForms
Playground
在这种情况下,您可以在 HTML
中的表单标记中使用(change)
<form #f="ngForm" (change)="changeField3()">
<mat-form-field appearance="fill">
<mat-label>Field 1</mat-label>
<input matInput name="field1" [(ngModel)]="MyItem.field1" (ngModelChange)="changeField2($event)">
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Field 2</mat-label>
<input matInput disabled name="field2" [(ngModel)]="MyItem.field2" >
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Field 3</mat-label>
<input matInput disabled name="field3" [(ngModel)]="MyItem.field3">
</mat-form-field>
</form>
并在 Ts
changeField3() {
this.MyItem.field3 = this.MyItem.field2 + ' modification field 3';
}
这种方法会监听表单模型中的每一个变化
我能够使用反应形式和 属性 ValueChanges
来做我需要的事情来捕捉控制器值何时发生变化。即使组件中的方法更改了控制器值,也会执行此操作。
这里有使用反应形式的相同示例: https://stackblitz.com/edit/angular-ivy-gh7zho
HTML 模板:
<form [formGroup]="testForm" (ngSubmit)="onSubmit()">
<mat-form-field appearance="fill">
<mat-label>Field 1</mat-label>
<input matInput name="field1" formControlName="field1" />
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Field 2</mat-label>
<input matInput name="field2" formControlName="field2" />
</mat-form-field>
<mat-form-field appearance="fill">
<mat-label>Field 3</mat-label>
<input matInput name="field3" formControlName="field3" />
</mat-form-field>
<button type="submit">Submit</button>
</form>
<button (click)="resetField2()">Reset field2</button>
组件
import { OnInit, Component, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Validators } from '@angular/forms';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
testForm: FormGroup = this.fb.group({
field1: [{ value: '', disabled: false }, Validators.required],
field2: [{ value: '', disabled: true }, Validators.required],
field3: [{ value: '', disabled: true }, Validators.required]
});
constructor(private fb: FormBuilder) {
const field1 = this.testForm.get('field1');
const field2 = this.testForm.get('field2');
field1!.valueChanges.subscribe(val => {
this.changeField2();
});
field2!.valueChanges.subscribe(val => {
this.changeField3();
});
}
changeField2() {
this.testForm
.get('field2')!
.setValue(this.testForm.get('field1')!.value + ' modification field 2'); //We can see that everytime field1 is changed is updating field2
}
changeField3() {
this.testForm
.get('field3')!
.setValue(this.testForm.get('field2')!.value + ' modification field 3'); //Eventhough we are updating field2, this is not being called
}
resetField2() {
this.testForm.get('field2')!.setValue(''); //This should leave field2 with only modification field 3
}
onSubmit() {
console.warn(this.testForm.value);
}
}