我有一个有几个数据字段和两个按钮的表单,只有当用户对表单做了一些更改时,我才想启用按钮。我试过使用:
this.form.valueChanges.subscribe(data => console.log('form changes', data));但是,当表单加载时,首先会检测到更改。是否有其他方法检查表单中是否有任何更改。我希望只在用户更改字段时才调用它,而不是在表单加载时调用它。以下是我的html和打字本代码:
profile.html:
<section>
<div>
<form [formGroup]="form">
<fieldset>
<div class="panel-group m-l-1 m-r-1 accordion vertical-scroll" id="">
<div class="form-group required no-gutter">
<label for="firstname"> First Name:</label>
<div class="col-md-7 col-lg-6">
<input type="text" class="form-control" id="firstname" placeholder="" name="firstname" title="firstname" formControlName="firstname" size="128" aria-required="true" maxlength="35">
</div>
</div>
</div>
</fieldset>
<div>
<button class="btn btn-primary" type="button" (click)="save()">Save</button>
<button class="btn btn-primary" type="button" (click)="cancel()">Cancel</button>
</div>
</form>
</div>
</section>profile.component.ts:
export class ProfileComponent implements OnInit, AfterViewInit, OnChanges {
public form: FormGroup;
constructor(private formBuilder: FormBuilder, private app: Application) {
}
loadForm(): void {
this.form = this.formBuilder.group({
firstname: [this.app.firstName, Validators.required]
});
this.form.valueChanges.subscribe(data => console.log('form changes', data));
}
save(): void {
}
cancel(): void {
};
ngOnInit() {
this.loadForm();
}
ngAfterViewInit() {
this.loadForm();
}
}发布于 2016-12-05 21:56:32
您可以使用.dirty (或.pristine)值来确定用户是否使用UI来更改控件值:
<button class="btn btn-primary" type="button" (click)="save()" [disabled]="!form.dirty" >Save</button>
<button class="btn btn-primary" type="button" [disabled]="!form.dirty"(click)="cancel()">Cancel</button>https://angular.io/docs/ts/latest/api/forms/index/AbstractControl-class.html#!#dirty-anchor
脏:如果用户更改了UI中的值,则布尔控件是脏的。 注意,对控件值的编程更改不会将其标记为脏。 触摸:布尔控件一旦用户触发模糊事件就会被标记为“触摸”。
发布于 2017-04-05 08:17:44
.dirty和.pristine布尔值的问题是,一旦它们改变了,它们就不会返回,即使您撤消了所引入的所有更改。我设法找到了一种解决这个问题的方法,方法是创建一个类来监视整个表单中的更改,并使用原始表单值检查更改的值。这样,如果用户更改被撤消,表单就可以回到原始状态,或者可以在可观察的(ReplaySubject)上发出一个布尔值,您可以提供和订阅。
其用途如下:
private _formIntactChecker:FormIntactChecker;
constructor(private _fb: FormBuilder) {
this._form = _fb.group({
...
});
// from now on, you can trust the .dirty and .pristine to reset
// if the user undoes his changes.
this._formIntactChecker = new FormIntactChecker(this._form);
}或者,类可以被配置为在表单从完整更改为修改时发出布尔值,而不是重置..pristine/.脏布尔值,反之亦然。真正的布尔表示,表单恢复到完整,而假布尔表示表单不再完好无损。
下面是一个如何使用它的示例:
private _formIntactChecker:FormIntactChecker;
constructor(private _fb: FormBuilder) {
this._form = _fb.group({
...
});
var rs = new ReplaySubject()
rs.subscribe((isIntact: boolean) => {
if (isIntact) {
// do something if form went back to intact
} else {
// do something if form went dirty
}
})
// When using the class with a ReplaySubject, the .pristine/.dirty
// will not change their behaviour, even if the user undoes his changes,
// but we can do whatever we want in the subject's subscription.
this._formChecker = new FormIntactChecker(this._form, rs);
}最后,完成所有工作的类:
import { FormGroup } from '@angular/forms';
import { ReplaySubject } from 'rxjs';
export class FormIntactChecker {
private _originalValue:any;
private _lastNotify:boolean;
constructor(private _form: FormGroup, private _replaySubject?:ReplaySubject<boolean>) {
// When the form loads, changes are made for each control separately
// and it is hard to determine when it has actually finished initializing,
// To solve it, we keep updating the original value, until the form goes
// dirty. When it does, we no longer update the original value.
this._form.statusChanges.subscribe(change => {
if(!this._form.dirty) {
this._originalValue = JSON.stringify(this._form.value);
}
})
// Every time the form changes, we compare it with the original value.
// If it is different, we emit a value to the Subject (if one was provided)
// If it is the same, we emit a value to the Subject (if one was provided), or
// we mark the form as pristine again.
this._form.valueChanges.subscribe(changedValue => {
if(this._form.dirty) {
var current_value = JSON.stringify(this._form.value);
if (this._originalValue != current_value) {
if(this._replaySubject && (this._lastNotify == null || this._lastNotify == true)) {
this._replaySubject.next(false);
this._lastNotify = false;
}
} else {
if(this._replaySubject)
this._replaySubject.next(true);
else
this._form.markAsPristine();
this._lastNotify = true;
}
}
})
}
// This method can be call to make the current values of the
// form, the new "orginal" values. This method is useful when
// you save the contents of the form but keep it on screen. From
// now on, the new values are to be considered the original values
markIntact() {
this._originalValue = JSON.stringify(this._form.value);
if(this._replaySubject)
this._replaySubject.next(true);
else
this._form.markAsPristine();
this._lastNotify = true;
}
}的重要性:小心处理初始值
该类使用JSON.stringify()快速比较整个formGroup值对象。但是,初始化控件值时要小心。
例如,对于复选框,必须将绑定它的值设置为布尔值。如果您使用其他类型,如“选中”、"0“、"1”等,则比较将无法正常工作。
<input type="checkbox" ... [(ngModel)]="variable"> <!-- variable must be a boolean -->同样适用于<select>,您必须将其值绑定到字符串,而不是数字:
<select ... [(ngModel)]="variable"> <!-- variable must be a string -->对于常规文本输入控件,也可以使用字符串:
<input type="text" ... [(ngModel)]="variable"> <!-- variable must be a string -->这里是一个例子,为什么否则它将无法工作。假设您有一个文本字段,并使用一个整数初始化它。原始值的字符串如下所示:
{ field1: 34,field2:“某些文本字段”}
但是,如果用户将field1更新为不同的值并返回到34,则新的字符串将是:
{字段:"34",field2:“某些文本字段”}
正如您所看到的,虽然表单并没有真正改变,但是由于数字34左右的引号,原始值和新值之间的字符串比较将导致false。
发布于 2017-06-16 07:26:55
首先使用"NgForm“。
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm)">
然后在"onSubmit()“函数上这样做-
onSubmit(myForm: NgForm): void {
let formControls = myForm.controls;
if(formControls.firstName.dirty) {
console.log("It's dirty");
}
else {
console.log("not dirty");
}
} 一定会成功的。您可以打印整个"myForm“并亲自查看可用的所有选项。
https://stackoverflow.com/questions/40982790
复制相似问题