代码之家  ›  专栏  ›  技术社区  ›  tatsu

动态表单输入值首次提交时未含水

  •  1
  • tatsu  · 技术社区  · 8 年前

    我有一张表格 n 输入:

        <form class="new-user" [formGroup]="customFields">
          <div *ngFor="let customField of customer['customFields']; let i = index">
              <div *ngIf="isEditing(i)" [@phaseAndSlideLeftAnimation] class="cusomer-property">
                  <mat-form-field>
                    <mat-label i18n="getFormKey(customField)">{{getFormKey(customField)}}</mat-label>
                    <input
                      ...
                      (keyup.enter)="finalizeEdit(customField, getFormKey(customField))"
                      (keyup.esc)="cancelEdit(customField)">
                    <mat-hint align="end">{{input.value?.length || 0}}/{{maxChars}}</mat-hint>
                  </mat-form-field>
              </div>
              <div *ngIf="isNotEditing(i)" [@phaseAndSlideLeftAnimation] class="cusomer-property pointer" (click)="viewEdit(customField)">
                  <div>{{getFormKey(customField)}}</div>
                  <div>{{getFormValue(customField)}}</div>
            </div>
          </div>
        </form>
    

    下面是我的动态表单初始化:

    if(this.customer && this.customer['customFields'].length){
          this.customer['customFields'].forEach((o, i) => {
            if(o['value']){
              this.customFields.addControl(o['name'], new FormControl(o['value'], Validators.required));
            } else {
              this.customer['customFields'][i]['value'] = '';
              this.customFields.addControl(o['name'], new FormControl(o['value'], Validators.required));
            }
          });
        }
    

    我遇到的问题是,我单击的第一个字段(然后通过 *ngIf )还没有水合物。

    Ergo在我的伪提交函数中:

      finalizeEdit(customField, key){
        console.log(this.customFields['value'][key]);
        customField['value'] = this.customFields['value'][key];
        this.popCustomFields.next(this.customer);
        this.closeEdit(customField); 
      }
    

    this.customFields['value'][key] (阅读: this.customFields.value.myinput )退货 undefined .

    …

    但是,如果我单击并打开第二个“自定义字段”或输入,那么现在我的所有输入值都在表单中正确地实例化,并达到最快速度。

    出于某种原因,这适用于表单的所有字段。

    你会认为这是其中之一 *NGIF -相关问题,但显然不是: 如果我揭示一个领域,那么就揭示另一个领域。他们现在都准备好了,之后的每一个领域都准备好了。

    因此,该错误仅在加载视图后的第一个“input ngif-explay”上发生。

    然后我发现了这个: https://codecraft.tv/courses/angular/forms/submitting-and-resetting/

    发现你可以这样做:

    <form (ngSubmit)="onSubmit()">
      .
      .
      .
    </form>
    

    希望这个功能在点火时能正确地得到水合物值,即使是在第一次提交时…

    因为在我的情况下,我不在乎整个表单上的提交被解雇,所以这对我来说是可行的。

    这是我的困惑:

    如果我想通过 customField 作为一个论点 finalizeEdit() ,我需要把 <form> 标记在dom中,在 *ngFor 为了能够传递变量,提交需要。

    问题是这会导致 n 一种输入形式,而不是一种形式 n 输入并破坏表单背后的整个代码。

    我觉得这会使我的代码更糟。

    另外,我还必须将每个表单提取到一个组件中,以正确初始化表单。

    所有这些都没有保证这将解决我的“第一次点击”的错误。

    理想情况下,我可以把 (ngSubmit)="onSubmit()" 在 <input> 而不是打开 <表格> 但我试过了,这不是一个可行的方法。

    无论如何,我怀疑表格的提交并不能解决我的问题。为什么不在第一次尝试时实例化输入字段?

    编辑(2018年7月16日):

    在试验之后,我可以确认onsubmit不是一个解决方案,因为它只点火一次,如果在初始点火之前打开一行中的两个或多个字段,则根本无法点火。

    2 回复  |  直到 8 年前
        1
  •  1
  •   bodorgergely    8 年前

    FormBuilder FormGroup FormArray customers 数据使我的工作更容易),并实现我认为将解决您的问题。

    这是 working example 在Stackblitz。

    模块

    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { FormsModule, ReactiveFormsModule } from '@angular/forms';
    
    import { AppComponent } from './app.component';
    
    @NgModule({
      imports: [BrowserModule, FormsModule, ReactiveFormsModule],
      declarations: [AppComponent],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    

    组件

    import { Component, OnInit } from '@angular/core';
    import { FormBuilder, FormGroup, FormArray, FormControl, Validators } from '@angular/forms';
    import { distinctUntilChanged, debounceTime } from 'rxjs/operators';
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent implements OnInit {
    
      form: FormGroup;
      customer = {
        customFields: [
          { value: 'one', key: 'first', isEditing: false },
          { value: 'two', key: 'second', isEditing: false },
          { value: 'three', key: 'third', isEditing: false },
          { value: 'four', key: 'fourth', isEditing: false }
        ]
      };
    
      get fields() {
        return this.form.get('fields') as FormArray;
      }
    
      constructor(private fb: FormBuilder) { }
    
      ngOnInit() {
        this.form = this.fb.group({
          fields: this.fb.array([])
        });
        if (this.customer && this.customer.customFields && this.customer.customFields.length) {
          this.customer.customFields.forEach(field => {
            if (!field.value) {
              field.value = '';
            }
            this.fields.push(this.fb.control(field.value, Validators.required));
          });
        }
        this.watchFormChanges();
      }
    
      saveEdit(index: number) {
        this.customer.customFields[index].value = this.fields.at(index).value;
        this.toggleEdit(index);
      }
    
      cancelEdit(index: number) {
        this.fields.at(index).setValue(this.customer.customFields[index].value);
        this.toggleEdit(index);
      }
    
      toggleEdit(index: number) {
        const isEditing = this.customer.customFields[index].isEditing;
        this.customer.customFields[index].isEditing = !this.customer.customFields[index].isEditing;
      }
    
      private watchFormChanges() {
        this.form.get('fields').valueChanges
          .pipe(distinctUntilChanged(), debounceTime(500))
          .subscribe(value => console.log(value));
      }
    
    }
    

    HTML

    <form [formGroup]="form">
      <div formArrayName="fields">
        <div *ngFor="let field of fields.controls; let i=index">
    
          <ng-container *ngIf="customer.customFields[i].isEditing; then editing else displaying"></ng-container>
    
          <ng-template #editing>
            <div class="field">
              <label [for]="i">{{ customer?.customFields[i].key }}:</label>
              <input [id]="i" class="value" type="text" [formControlName]="i (keyup.enter)="saveEdit(i)" (keyup.esc)="cancelEdit(i)">
            </div>
          </ng-template>
    
          <ng-template #displaying>
            <div class="field">
              <label>{{ customer?.customFields[i].key }}:</label>
              <span class="value" [title]="fields.getRawValue()[i]" (click)="toggleEdit(i)">{{fields.getRawValue()[i]}}</span>
            </div>
          </ng-template>
    
        </div>
      </div>
    </form>
    
        2
  •  1
  •   Hooter    8 年前

    自定义字段有问题。 据我所知,你是从第一个领域提交的。但事实证明,该字段尚未将其值转移到表单。在这种情况下,我有点耽搁了 setTimeout .

    推荐文章