提交后重置 Angular 2 中的表单

Resetting a form in Angular 2 after submit

我知道 Angular 2 目前缺少一种方法可以轻松地将表单重置为原始状态。四处寻找,我找到了一种解决方案,如下所示,可以重置表单字段。

有人建议我需要删除控制组并创建一个新组以将表单重建为原始状态。我很难找出最好的方法来做到这一点。我知道我需要将表单构建包装在一个函数中,但是在构造函数中这样做时我 运行 出错了。

重建控制组以完全重置表单的最佳方法是什么?

class App {

    name: Control;
    username: Control;
    email: Control;

    form: ControlGroup;

    constructor(private builder: FormBuilder) {

        this.name = new Control('', Validators.required);
        this.email = new Control('', Validators.required);
        this.username = new Control('', Validators.required);

        this.form = builder.group({
            name: this.name,
            email: this.email,
            username: this.username
        });
    }

    onSubmit(value: any): void {  
        // code that happens when form is submitted
        // then reset the form
        this.reset();
    }

    reset() {
        for (let name in this.form.controls) {
            this.form.controls[name].updateValue('');
            this.form.controls[name].setErrors(null);
        }
    }
}

>=RC.6

支持重置表单并保持 submitted 状态。

console.log(this.form.submitted);
this.form.reset()

this.form = new FormGroup()...;

导入更新

要在创建表单时将表单控件设置为某个状态,例如验证器,需要进行一些额外的测量

在表单的视图部分 (html) 添加一个 *ngIf 来显示或隐藏表单

<form *ngIf="showForm"

在表单的组件端 (*.ts) 执行此操作

  showForm:boolean = true;

  onSubmit(value:any):void {
    this.showForm = false;
    setTimeout(() => {
    this.reset()
      this.showForm = true;
    });
  }

这里有一个更详细的例子:

export class CreateParkingComponent implements OnInit {
  createParkingForm: FormGroup ;
  showForm = true ;

  constructor(
    private formBuilder: FormBuilder,
    private parkingService: ParkingService,
    private snackBar: MatSnackBar) {

      this.prepareForm() ;
  }

  prepareForm() {
    this.createParkingForm = this.formBuilder.group({
      'name': ['', Validators.compose([Validators.required, Validators.minLength(5)])],
      'company': ['', Validators.minLength(5)],
      'city': ['', Validators.required],
      'address': ['', Validators.compose([Validators.required, Validators.minLength(10)])],
      'latitude': [''],
      'longitude': [''],
      'phone': ['', Validators.compose([Validators.required, Validators.minLength(7)])],
      'pictureUrl': [''],
      // process the 3 input values of the maxCapacity'
      'pricingText': ['', Validators.compose([Validators.required, Validators.minLength(10)])],
      'ceilingType': ['', Validators.required],
    });
  }

  ngOnInit() {
  }


  resetForm(form: FormGroup) {
    this.prepareForm();
  }

  createParkingSubmit() {
    // Hide the form while the submit is done
    this.showForm = false ;

    // In this case call the backend and react to the success or fail answer

    this.parkingService.create(p).subscribe(
      response => {
        console.log(response);
        this.snackBar.open('Parqueadero creado', 'X', {duration: 3000});
        setTimeout(() => {
          //reset the form and show it again
          this.prepareForm();
            this.showForm = true;
          });
      }
      , error => {
        console.log(error);
        this.showForm = true ;
        this.snackBar.open('ERROR: al crear Parqueadero:' + error.message);
      }
      );
  }
}

Plunker example

原版 <= RC.5 只需将创建表单的代码移动到一个方法中,并在处理提交后再次调用它:

@Component({
  selector: 'form-component',
  template: `
    <form (ngSubmit)="onSubmit($event)" [ngFormModel]="form">
       <input type="test" ngControl="name">
       <input type="test" ngControl="email">
       <input type="test" ngControl="username">
       <button type="submit">submit</button>
    </form>
    <div>name: {{name.value}}</div>
    <div>email: {{email.value}}</div>
    <div>username: {{username.value}}</div>
`
})
class FormComponent {

  name:Control;
  username:Control;
  email:Control;

  form:ControlGroup;

  constructor(private builder:FormBuilder) {
    this.createForm();
  }

  createForm() {
    this.name = new Control('', Validators.required);
    this.email = new Control('', Validators.required);
    this.username = new Control('', Validators.required);

    this.form = this.builder.group({
      name: this.name,
      email: this.email,
      username: this.username
    });
  }

  onSubmit(value:any):void {
    // code that happens when form is submitted
    // then reset the form
    this.reset();
  }

  reset() {
    this.createForm();
  }
}

Plunker example

对于 Angular 2 Final,我们现在有一个新的 API 可以完全重置表格:

@Component({...})
class App {

    form: FormGroup;
     ...
    reset() {
       this.form.reset();
   }
}

这个 API 不仅重置了表单值,还将表单字段状态设置回 ng-pristineng-untouched.

当我浏览 Angular 表单基础指南并点击重置表单部分时,当我阅读以下关于他们提供的解决方案时,我感到非常惊讶。

This is a temporary workaround while we await a proper form reset feature.

我个人没有测试过他们提供的解决方法是否有效(我假设有效),但我相信它并不完美,并且必须有更好的方法来解决这个问题。

根据FormGroup API(标记为稳定)已经有一个'reset'方法。

我尝试了以下方法。在我的 template.html 文件中,我有

<form (ngSubmit)="register(); registrationForm.reset();" #registrationForm="ngForm">
    ...
</form>

请注意,在表单元素中,我已经初始化了一个模板引用变量 'registrationForm' 并将其初始化为 ngForm Directive,即 "governs the form as a whole"。这使我能够访问管理 FormGroup 的方法和属性,包括 reset() 方法。

如上所示将此方法调用绑定到 ngSubmit 事件,在 register() 方法完成后重置表单(包括原始、脏、模型状态等)。对于演示来说,这还可以,但是对于实际应用来说并不是很有帮助。

假设 register() 方法执行对服务器的调用。当我们知道服务器响应一切正常时,我们想重置表单。将代码更新为以下内容以适应这种情况。

在我的 template.html 文件中:

<form (ngSubmit)="register(registrationForm);" #registrationForm="ngForm">
    ...
</form>

在我的 component.ts 文件中:

@Component({
  ...
})
export class RegistrationComponent {
  register(form: FormGroup) {

   ...

   // Somewhere within the asynchronous call resolve function
   form.reset();
  }
}

将 'registrationForm' 引用传递给该方法将使我们能够在我们想要的执行点调用重置方法。

希望这对您有所帮助。 :)

注意:该方法基于Angular 2.0.0-rc.5

如果您只调用 reset() 函数,表单控件将不会设置为原始状态。 android.io 文档有针对此问题的解决方案。

component.ts

  active = true; 

  resetForm() {
      this.form.reset();
      this.active = false;
      setTimeout(() => this.active = true, 0);
  }

component.html

<form *ngIf="active">

我在类似的情况下使用了 Günter Zöchbauer 的答案,这对我来说是完美的,将表单创建移动到一个函数并从 ngOnInit() 调用它。

为了说明,我就是这样做的,包括字段初始化:

ngOnInit() {
    // initializing the form model here
    this.createForm();
}

createForm() {
    let EMAIL_REGEXP = /^[^@]+@([^@\.]+\.)+[^@\.]+$/i; // here just to add something more, useful too

    this.userForm = new FormGroup({
        name: new FormControl('', [Validators.required, Validators.minLength(3)]),
        city: new FormControl(''),
        email: new FormControl(null, Validators.pattern(EMAIL_REGEXP))
    });

    this.initializeFormValues();
}

initializeFormValues() {
    const people = {
        name: '',
        city: 'Rio de Janeiro',  // Only for demonstration
        email: ''
    };
    (<FormGroup>this.userForm).setValue(people, { onlySelf: true });
}

resetForm() {
    this.createForm();
    this.submitted = false;
}

我在表单中添加了一个用于智能重置的按钮(带有字段初始化):

在 HTML 文件(或内联模板)中:

<button type="button" [disabled]="userForm.pristine" (click)="resetForm()">Reset</button>

第一次加载表单或单击重置按钮后,我们有以下状态:

FORM pristine: true 
FORM valid: false (because I have required a field) 
FORM submitted: false
Name pristine: true
City pristine: true
Email pristine: true

以及简单的 form.reset() 无法完成的所有字段初始化! :-)

我不知道我是否走在正确的道路上,但我使用以下 form/submit 标签在 ng 2.4.8 上运行:

<form #heroForm="ngForm" (ngSubmit)="add(newHero); heroForm.reset()">
<!-- place your input stuff here -->
<button type="submit" class="btn btn-default" [disabled]="!heroForm.valid">Add hero</button>

似乎成功了,再次将表单的字段设置为 "pristine"。

使用 NgForm.resetForm() 而不是 .reset() 因为它是 NgForm 的 public [=27] 中正式记录的方法=]. (参考 [1])

<form (ngSubmit)="mySubmitHandler(); myNgForm.resetForm()" #myNgForm="ngForm">

.resetForm() 方法将重置 NgFormFormGroup 并将其 submit 标志设置为 false(参见 [2 ]).

Tested in @angular versions 2.4.8 and 4.0.0-rc3

我在 angular 4 中使用反应式形式,这种方法对我有用:

    this.profileEditForm.reset(this.profileEditForm.value);

请参阅基础文档reset the form flags

请使用以下格式,它非常适合我..我已经检查了很多方法,但这个非常有效。<form (ngSubmit)="mySubmitHandler(); myNgForm.resetForm()" #myNgForm="ngForm"> .... </form>

如果有人只想清除一个特定的表单控件,可以使用

formSubmit(){
this.formName.patchValue({
         formControlName:''
          //or if one wants to change formControl to a different value on submit
          formControlName:'form value after submission'     
    });
}

现在NgForm支持两种方法: .reset() vs .resetForm() 后者还将表单的提交状态更改为 false 并将其控件恢复为初始状态。

form: NgForm;

form.reset()

这对我不起作用。它清除了值,但控件引发了错误。

但对我有用的是创建一个隐藏的重置按钮并在我们想要清除表单时单击该按钮。

<button class="d-none" type="reset" #btnReset>Reset</button>

然后在组件上,定义 ViewChild 并在代码中引用它。

@ViewChild('btnReset') btnReset: ElementRef<HTMLElement>;

使用此重置表单。

this.btnReset.nativeElement.click();

请注意 class d-none 在按钮上设置 display: none;