Passing data in saveRow() using FormArray?

2019-09-19 14:06发布

问题:

> ## app.component.ts ##

When click on SAve Button, I get error, ERROR TypeError: Cannot read property 'value' of undefined

When passing addRow(name.value) in second row it worked fine. But, when I pass it is first row as saveRow(name.value).!!! ERROR TypeError: Cannot read property 'value' of undefined.....................I also tried saveRow(name) than error doesnot come but value passed is undefined!

<div class="container">
    <div class="row">
        <form [formGroup]="form1">
            <div class="form-group">
                <table class="table">
                    <thead>
                        <tr>
                            <td>S.No</td>
                            <td>NAME</td>
                            <td>WEIGHT(in grams)</td>
                            <td>QUANTITY</td>
                        </tr>
                    </thead>
                    <tbody>
                        <tr *ngFor="let i of form1.get('id').value; let k = index">
                            <td>
                                <ng-container *ngIf="tempindex !== k">{{ form1.get('id').value[k] }}</ng-container>
                            </td>
                            <td>
                                <ng-container *ngIf="tempindex !== k">{{ form1.get('name').value[k] }}</ng-container>
                                <input type="text" *ngIf="tempindex === k" [value]="form1.get('name').value[k]" #name>
                            </td>
                            <td>
                                <ng-container *ngIf="tempindex !== k">{{ form1.get('weight').value[k] }}</ng-container>
                                <input type="text" *ngIf="tempindex === k" [value]="form1.get('name').value[k]" #weight>
                            </td>
                            <td>
                                <ng-container *ngIf="tempindex !== k">{{ form1.get('quantity').value[k] }}</ng-container>
                                <input type="text" *ngIf="tempindex === k" [value]="form1.get('quantity').value[k]" #quantity>
                            </td>
                            <td>
                                <ng-container *ngIf="tempindex === k">
                                    <button *ngIf="editclicked" class="btn btn-primary" (click)="saveRow(k, name.value, weight.value, quantity.value)">Save</button>
                                </ng-container>

                                <button *ngIf="!editclicked" class="btn btn-primary" (click)="editRow(k)">Edit</button> &nbsp;&nbsp;
                                <button *ngIf="!editclicked" class="btn btn-danger" (click)="delRow(k)">Delete</button>
                            </td>
                        </tr>
                        <button *ngIf="!addclicked" class="btn btn-default" (click)="addRow()">ADD</button>
                        <tr *ngIf="addclicked">
                            <td></td>
                            <td>
                                <input type="text" #name>
                            </td>
                            <td>
                                <input type="text" #weight>
                            </td>
                            <td>
                                <input type="text" #quantity>
                            </td>
                            <td><button class="btn btn-primary" (click)="hitadd(name.value, weight.value, quantity.value)">Add</button>&nbsp;&nbsp;
                                <button class="btn btn-danger" (click)="hitcancel()">Cancel</button>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </form>
    </div>
</div>

app.component.html

First tr is used to fetch all fields from FormArrays

Second tr is used to add new data to the FormArrays (Problem!!!)

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, FormArray } from '@angular/forms'
import { element } from 'protractor';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'app';
  form1: FormGroup;
  addclicked = false;
  tempId = '';
  tempindex;
  editclicked = false;

  ngOnInit() {
    this.form1 = new FormGroup({
      'id': new FormArray([]),
      'name': new FormArray([]),
      'weight': new FormArray([]),
      'quantity': new FormArray([])


      // 'id': new FormArray([new FormControl('1'), new FormControl('2')]),
      // 'name': new FormArray([new FormControl('Beans'), new FormControl('Soup')]),
      // 'weight': new FormArray([new FormControl('100'), new FormControl('125')]),
      // 'quantity': new FormArray([new FormControl('60'), new FormControl('20')])

    });
  }
  addRow(){
    this.addclicked = true;
    this.tempId = '';
  }
  hitcancel(){
    this.addclicked = false;
    this.tempId = '';
  }
  hitadd(name, weight, quantity){
    this.tempId = (this.ids.value.length + 1).toString(10);

    this.ids.push(new FormControl(this.tempId));
    this.names.push(new FormControl(name));
    this.weights.push(new FormControl(weight));
    this.quantities.push(new FormControl(quantity));

    this.tempId = '';
    this.addclicked = false;

  }

  editRow(index: number){
    this.editclicked = true;
    this.tempindex = index;

    //this.ids.at(index).patchValue(null);
  }

  saveRow(index, name, weight, quantity){
    this.editclicked = false;
    this.tempindex = undefined;
    console.log(name);
    // console.log(this.names.at(index).setValue(name));
    // this.weights.at(index).setValue(weight);
    // this.quantities.at(index).setValue(quantity);
  }

  delRow(index: number){
    this.addclicked = false;

    this.ids.removeAt(index);
    this.names.removeAt(index);
    this.weights.removeAt(index);
    this.quantities.removeAt(index);

    let i = 0;
    this.ids.controls.forEach(element => {
      i++;
      element.setValue(i.toString(10))
    });
  }
  get ids(){
    return this.form1.get('id') as FormArray;
  }
  get names(){
    return this.form1.get('name') as FormArray;
  }
  get weights(){
    return this.form1.get('weight') as FormArray;
  }
  get quantities(){
    return this.form1.get('quantity') as FormArray;
  }
}
<!-- end snippet -->

回答1:

I have updated the above code but emitting non-important element according to my prospective. Please take a look.

These are the modifications:

app.component.ts

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, FormArray } from '@angular/forms'
import { element } from 'protractor';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'app';
  form1: FormGroup;
  addclicked = false;
  tempId = '';

  ngOnInit() {
    this.form1 = new FormGroup({
      'id': new FormArray([]),
      'name': new FormArray([]),
      'weight': new FormArray([]),
      'quantity': new FormArray([])

      // 'id': new FormArray([new FormControl('1'), new FormControl('2')]),
      // 'name': new FormArray([new FormControl('Beans'), new FormControl('Soup')]),
      // 'weight': new FormArray([new FormControl('100'), new FormControl('125')]),
      // 'quantity': new FormArray([new FormControl('60'), new FormControl('20')])

    });
  }
  addRow(){
    this.addclicked = true;
    this.tempId = '';
  }
  hitcancel(){
    this.addclicked = false;
    this.tempId = '';
  }

  hitadd(name, weight, quantity){
    this.tempId = (this.ids.value.length + 1).toString(10);

    this.ids.push(new FormControl(this.tempId));
    this.names.push(new FormControl(name));
    this.weights.push(new FormControl(weight));
    this.quantities.push(new FormControl(quantity));

    this.tempId = '';
    this.addclicked = false;
  }

  editRow(index: number){
  }

  delRow(index: number){
    this.ids.removeAt(index);
    this.names.removeAt(index);
    this.weights.removeAt(index);
    this.quantities.removeAt(index);

    let i = 0;
    this.ids.controls.forEach(element => {
      i++;
      element.setValue(i.toString(10))
    });
  }
  get ids(){
    return this.form1.get('id') as FormArray;
  }
  get names(){
    return this.form1.get('name') as FormArray;
  }
  get weights(){
    return this.form1.get('weight') as FormArray;
  }
  get quantities(){
    return this.form1.get('quantity') as FormArray;
  }
}

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ReactiveFormsModule

  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.html

<div class="container">
<div class="row">
    <form [formGroup]="form1">
        <div class="form-group">
            <table class="table">
                <thead>
                    <tr>
                        <td>S.No</td>
                        <td>NAME</td>
                        <td>WEIGHT(in grams)</td>
                        <td>QUANTITY</td>
                    </tr>
                </thead>
                <tbody>
                    <tr *ngFor="let i of form1.get('id').value; let k = index">
                        <td>{{ form1.get('id').value[k] }}</td>
                        <td>{{ form1.get('name').value[k] }}</td>
                        <td>{{ form1.get('weight').value[k] }}</td>
                        <td>{{ form1.get('quantity').value[k] }}</td>
                        <td><button class="btn btn-primary" (click)="editRow(k)">Edit</button>&nbsp;&nbsp;<button class="btn btn-danger"
                                (click)="delRow(k)">Delete</button></td>
                    </tr>
                    <button *ngIf="!addclicked" class="btn btn-default" (click)="addRow()">ADD</button>
                    <tr *ngIf="addclicked">
                        <td></td>
                        <td>
                            <input type="text" #name>
                        </td>
                        <td>
                            <input type="text" #weight>
                        </td>
                        <td>
                            <input type="text" #quantity>
                        </td>
                        <td><button class="btn btn-primary" (click)="hitadd(name.value, weight.value, quantity.value)">Add</button>&nbsp;&nbsp;
                            <button
                                class="btn btn-danger" (click)="hitcancel()">Cancel</button>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    </form>
</div>


In light of the code modifications that you have undergone, try to see if this fixes the error you are getting,

<td>
                                <ng-container *ngIf="tempindex !== k">{{ form1.get('id').value[k] }}</ng-container>
                            </td>
                            <td>
                                <ng-container *ngIf="tempindex !== k">{{ form1.get('name').value[k]}}</ng-container>
                                <input type="text" *ngIf="tempindex === k" [value]="form1.get('name').value[k]" #nameEdit>
                            </td>
                            <td>
                                <ng-container *ngIf="tempindex !== k">{{ form1.get('weight').value[k] }}</ng-container>
                                <input type="text" *ngIf="tempindex === k" [value]="form1.get('name').value[k]" #weightEdit>
                            </td>
                            <td>
                                <ng-container *ngIf="tempindex !== k">{{ form1.get('quantity').value[k] }}</ng-container>
                                <input type="text" *ngIf="tempindex === k" [value]="form1.get('quantity').value[k]" #quantityEdit>
                            </td>
                            <td>
                                <ng-container *ngIf="tempindex === k">
                                    <button *ngIf="editclicked" class="btn btn-primary" (click)="saveRow(k, nameEdit.value, weightEdit.value, quantityEdit.value)">Save</button>
                                </ng-container>

                                <button *ngIf="!editclicked" class="btn btn-primary" (click)="editRow(k)">Edit</button> &nbsp;&nbsp;
                                <button *ngIf="!editclicked" class="btn btn-danger" (click)="delRow(k)">Delete</button>
                            </td>

In your component,

saveRow(index: number, name, weight, quantity){

    this.names.at(index).setValue(name));
    this.weights.at(index).setValue(weight);
    this.quantities.at(index).setValue(quantity);

    this.editclicked = false;
    this.tempindex = undefined;
  }

module

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ReactiveFormsModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

template

<div class="container">
    <div class="row">
        <form [formGroup]="form1">
            <div class="form-group">
                <table class="table">
                    <thead>
                        <tr>
                            <td>S.No</td>
                            <td>NAME</td>
                            <td>WEIGHT(in grams)</td>
                            <td>QUANTITY</td>
                        </tr>
                    </thead>
                    <tbody>
                        <tr *ngFor="let i of form1.get('id').value; let k = index">
                                <td>
                                        <ng-container *ngIf="tempindex !== k">{{ form1.get('id').value[k] }}</ng-container>
                                    </td>
                                    <td>
                                        <ng-container *ngIf="tempindex !== k">{{ form1.get('name').value[k]}}</ng-container>
                                        <input type="text" *ngIf="tempindex === k" [(ngModel)]="tempName" [ngModelOptions]="{standalone: true}">
                                    </td>
                                    <td>
                                        <ng-container *ngIf="tempindex !== k">{{ form1.get('weight').value[k] }}</ng-container>
                                        <input type="text" *ngIf="tempindex === k" [(ngModel)]="tempWeight" [ngModelOptions]="{standalone: true}">
                                    </td>
                                    <td>
                                        <ng-container *ngIf="tempindex !== k">{{ form1.get('quantity').value[k] }}</ng-container>
                                        <input type="text" *ngIf="tempindex === k" [(ngModel)]="tempQuantity" [ngModelOptions]="{standalone: true}">
                                    </td>
                                    <td>
                                        <ng-container *ngIf="tempindex === k">
                                            <button *ngIf="editclicked" class="btn btn-primary" (click)="saveRow(k, tempName, tempWeight, tempQuantity)">Save</button>
                                        </ng-container>

                                        <button *ngIf="!editclicked" class="btn btn-primary" (click)="editRow(k)">Edit</button> &nbsp;&nbsp;
                                        <button *ngIf="!editclicked" class="btn btn-danger" (click)="delRow(k)">Delete</button>
                                    </td>
                        </tr>
                        <button *ngIf="!addclicked" class="btn btn-default" (click)="addRow()">ADD</button>
                        <tr *ngIf="addclicked">
                            <td></td>
                            <td>
                                <input type="text" #name>
                            </td>
                            <td>
                                <input type="text" #weight>
                            </td>
                            <td>
                                <input type="text" #quantity>
                            </td>
                            <td><button class="btn btn-primary" (click)="hitadd(name.value, weight.value, quantity.value)">Add</button>&nbsp;&nbsp;
                                <button class="btn btn-danger" (click)="hitcancel()">Cancel</button>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </form>
    </div>
</div>

component

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, FormArray } from '@angular/forms'
import { element } from 'protractor';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'app';
  form1: FormGroup;
  addclicked = false;
  tempId = '';
  tempName = '';
  tempWeight = '';
  tempQuantity = '';
  tempindex;
  editclicked = false;

  ngOnInit() {
    this.form1 = new FormGroup({
      'id': new FormArray([]),
      'name': new FormArray([]),
      'weight': new FormArray([]),
      'quantity': new FormArray([])


      // 'id': new FormArray([new FormControl('1'), new FormControl('2')]),
      // 'name': new FormArray([new FormControl('Beans'), new FormControl('Soup')]),
      // 'weight': new FormArray([new FormControl('100'), new FormControl('125')]),
      // 'quantity': new FormArray([new FormControl('60'), new FormControl('20')])

    });
  }
  addRow(){
    this.addclicked = true;
    this.tempId = '';
  }
  hitcancel(){
    this.addclicked = false;
    this.tempId = '';
  }
  hitadd(name, weight, quantity){
    this.tempId = (this.ids.value.length + 1).toString(10);

    this.ids.push(new FormControl(this.tempId));
    this.names.push(new FormControl(name));
    this.weights.push(new FormControl(weight));
    this.quantities.push(new FormControl(quantity));

    this.tempId = '';
    this.addclicked = false;

    console.log(this.form1);
  }

  editRow(index: number) {
    this.tempName = this.names.value[index];
    this.tempWeight = this.weights.value[index];
    this.tempQuantity = this.quantities.value[index];
    this.editclicked = true;
    this.tempindex = index;

    //this.ids.at(index).patchValue(null);
  }

  saveRow(index: number, name, weight, quantity){

        this.names.at(index).setValue(name);
        this.weights.at(index).setValue(weight);
        this.quantities.at(index).setValue(quantity);

        this.editclicked = false;
        this.tempindex = undefined;
      }

  delRow(index: number){
    this.addclicked = false;

    this.ids.removeAt(index);
    this.names.removeAt(index);
    this.weights.removeAt(index);
    this.quantities.removeAt(index);

    let i = 0;
    this.ids.controls.forEach(element => {
      i++;
      element.setValue(i.toString(10))
    });
  }
  get ids(){
    return this.form1.get('id') as FormArray;
  }
  get names(){
    return this.form1.get('name') as FormArray;
  }
  get weights(){
    return this.form1.get('weight') as FormArray;
  }
  get quantities(){
    return this.form1.get('quantity') as FormArray;
  }
}

This one works. Please remove unwanted contented from the code here if you like. Just showing it fully here for now.



标签: angular