typescript - Angular 2/4 Rediger Skjema Fyll FormArray-kontroller


Jeg prøver å implementere et redigeringsskjema for en modell med nestede attributter (FormArray). Jeg har problemer med syntaksen, og jeg er usikker på om jeg er på rett spor. Attributtene for hovedskjemaet fungerer, det er det nestede skjemaet jeg har problemer med. Her er hva jeg har så langt.

Her starter jeg skjema-gruppen:

private initForm() {
  this.subscription = this.expenseService.getExpense(this.id)
    .subscribe(
      expense => {
        this.expense = expense;
        this.patchForm();
      }
    );
  this.expenseEditForm = this.fb.group({
    date: '',
    amount: '',
    check_number: '',
    debit: '',
    payee_id: '',
    notes: '',
    expense_expense_categories_attributes:[]
  });
}

Her oppdaterer jeg skjemaet for å sette verdier fra et objekt hentet fra backend-API-et mitt.

private patchForm() {
  this.expenseEditForm.setValue({
    date: '',
    amount: this.expense.amount_cents,
    check_number: this.expense.check_number,
    debit: this.expense.debit,
    payee_id: '',
    notes: this.expense.notes,
    expense_expense_categories_attributes:  this.fb.array([
      this.setExpenseCategories(),
    ])
  });
}

Dette er hvor jeg sitter fast. Hvordan kan jeg legge til i et FormArray. Hvis jeg prøver å legge til, får jeg en feil som sier at push ikke eksisterer på FormArray.

private setExpenseCategories() {
  for ( let expenseCategories of this.expense.expense_expense_categories){
    this.fb.array.push([
       this.fb.group({
        expense_category_id: [expenseCategories.expense_category_id, Validators.required],
        amount: [expenseCategories.amount_cents]
      ])
    });
  }
}

Bare i tilfelle det trengs. Her er min html.

<div
  *ngFor="let expensecategoriesCtl of expenseEditForm.controls.expense_expense_categories_attributes.controls let i = index"
  [formGroupName]="i"
  style="margin-top: 10px;">

  <md-card>
    <md-select class="full-width-input"
               placeholder="Expense Category"
               id="expense_category_id"
               formControlName="expense_category_id"
    >

      <md-option *ngFor="let expenseCategory of expenseCategories" value="{{expenseCategory.id}}">
        {{expenseCategory.category}}
      </md-option>
    </md-select>

    <md-input-container class="full-width-input">
      <input
        mdInput placeholder="Amount"
        type="number"
        formControlName="amount">
    </md-input-container>
  </md-card>
</div>

Svar #1

Noen endringer i DeborahKs svar, siden expense.expense_expense_categories ikke inneholder primitive typer, men objekter. Derfor kan vi ikke tilordne verdiene som de er, men hvert objekt må pakkes inn i en FormGroup, akkurat som du har forsøkt.

Her har jeg en forkortet versjon av koden din:

Bygg skjemaet:

ngOnInit() {
  this.expenseEditForm = this.fb.group({
    notes: [''],
    // notice below change, we need to mark it as an formArray
    expense_expense_categories_attributes: this.fb.array([])
})

Så kaller vi patchForm i tilbakeringingen, akkurat som du har gjort. Den funksjonen vil se slik ut, merk at vi kaller this.setExpenseCategories utenfor:

patchForm() {
  this.expenseEditForm.patchValue({
    notes: this.expense.notes,
  })
  this.setExpenseCategories()
}

Deretter kommer den største endringen fra din eksisterende kode, der vi først tildeler FormArray til variabelen control og deretter itererer vi gjennom arrayet ditt mottatt fra backend, oppretter en FormGroup for hvert objekt og legger objektet til hver FormGroup:

setExpenseCategories(){
  let control = <FormArray>this.expenseEditForm.controls.expense_expense_categories_attributes;
  this.expense.expense_expense_categories.forEach(x => {
    control.push(this.fb.group(x));
  })
}

Deretter til malen, dette eksempelet er uten Angular Material:

<form [formGroup]="expenseEditForm">
  <label>Notes: </label>
  <input formControlName="notes" /><br>
  <!-- Declare formArrayName -->
  <div formArrayName="expense_expense_categories_attributes">
    <!-- iterate formArray -->
    <div *ngFor="let d of expenseEditForm.get('expense_expense_categories_attributes').controls; let i=index"> 
      <!-- Use the index for each formGroup inside the formArray -->
      <div [formGroupName]="i">
      <label>Amount: </label>
        <input formControlName="amount" />
      </div>
    </div>
  </div>
</form>

Endelig en

Demo

Svar #2

Hvis jeg forstår spørsmålet ditt riktig, kan det hende du trenger noe slik:

    // Update the data on the form
    this.productForm.patchValue({
        productName: this.product.productName,
        productCode: this.product.productCode,
        starRating: this.product.starRating,
        description: this.product.description
    });
    this.productForm.setControl('tags', this.fb.array(this.product.tags || []));

Du kan se hele eksemplet her: https://github.com/DeborahK/Angular2-ReactiveForms i mappen APM - Updated.

Relaterte artikler