簡體   English   中英

我將如何將來自多個子組件的表單輸入綁定到父組件中定義的數組?

[英]How would I go about binding form input from multiple child components to an array defined in a parent component?

我正在嘗試將來自多個子組件( item-input-component )的表單輸入綁定到父組件( add-invoice-component )中定義的數組itemList[] 我想獲取三個輸入( itemNamequantityprice ),從中創建一個Item對象,然后從item-input-component輸出該Item對象並將其添加到itemList[] 我怎樣才能做到這一點 ? 這甚至可能嗎? 如果沒有,什么是好的解決方案?

添加發票組件.html

 <form> 
    <div>
        <h2>Items</h2>
        <app-item-input *ngFor="let item of numArray"></app-item-input>
        <button (click)="incrementNumOfItems()">Add Item</button>
    </div>
</form>

添加發票組件.ts

import { Component, ElementRef, OnInit, Renderer2 } from '@angular/core';
import { Item } from 'src/app/models/item';

@Component({
  selector: 'app-add-invoice',
  templateUrl: './add-invoice.component.html',
  styleUrls: ['./add-invoice.component.css']
})
export class AddInvoiceComponent implements OnInit {

  description!: string;
  invoiceDate!: Date;
  clientName!: string;
  clientAddress!: string;
  itemList!: Item[];
  numOfItems: number = 2;
  numArray: number[] = Array(2).fill(0).map((x,i)=>i);

  constructor( private el: ElementRef) { }


  ngOnInit(): void {
  }

  incrementNumOfItems() {
    this.numOfItems++;
    this.numArray = Array(this.numOfItems).fill(0).map((x,i)=>i);
  }


  removeItem() {
    this.el.nativeElement.remove()
  }
}

項目輸入組件.html

<div class="mb-3 row item">
<div class="col">
    <label for="item-name" class="form-label">Item Name</label>
    <input type="text" id="item-name" name="clientName" class="form-control">
</div>

<div class="col">
    <label for="quantity" class="form-label">Quantity</label>
    <input type="text" id="quantity" name="quantity" class="form-control">
</div>

<div class="col">
    <label for="price" class="form-label">Price</label>
    <input type="text" id="price" name="price" class="form-control">
</div>

<button (click)="removeItem()">Delete Item</button>

項目輸入組件.ts

import { Component, ElementRef, OnInit , Renderer2} from '@angular/core';

@Component({
  selector: 'app-item-input',
  templateUrl: './item-input.component.html',
  styleUrls: ['./item-input.component.css']
})
export class ItemInputComponent implements OnInit {

  itemName!: string;
  quantity!: number;
  price!: number;

  constructor(private el: ElementRef) { }

  ngOnInit(): void {
  }

  removeItem() {
    this.el.nativeElement.remove()
  }
}

項目.ts

export interface Item {
    itemName: string,
    quantity: number,
    price: number
}

問題是關於將對象傳遞給您的子組件,刪除您需要使用輸出與父組件進行通信

這個對象將是一個具有以下屬性的對象:itemName、數量和價格 - 你使用 [(ngModel)] 或 FormGroup - 你使用 ReactiveForms-

  @Input()element:any
  @Output() deleteItem:EventEmitter<any>:new EventEmitter<any>()

<input ... [(ngModel)]="element.clientName">
<input ... [(ngModel)]="element.quantity">
<input ... [(ngModel)]="element.price">

<button (click)="deleteItem.emit(null)">Delete Item</button>

你的父母

<app-item-input *ngFor="let item of list;let i=index"
   [element]="list[i]"
   (deleteItem)="removeItem(i)"
></app-item-input>

在哪里

list:any[]=this.numArray.map(_=>({
     clientName:'',
     quantity:0,
     price:0
}))

//see that removeItem remove one value of the array.
//**NOT** about your .html
removeItem(index:number) {
  this.list.splice(index,1)
}

使用 FormArray 看起來像

  formGroup:FormGroup;
  @Input('group') set _group(value)
  {
     this.formGroup=value as FormGroup
  }

  @Output() deleteItem:EventEmitter<any>:new EventEmitter<any>()

<form [formGroup]="fromGroup">
 <input ... formControlName="clientName">
 <input ... formControlName="quantity">
 <input ... formControlName="price">
</form>

<button (click)="deleteItem.emit(null)">Delete Item</button>

和家長

<app-item-input *ngFor="let item of listFormArray.controls;let i=index"
   [group]="listFormArray.at(i)"
   (deleteItem)="removeItem(i)"
></app-item-input>

listFormArray:FormArray[]=new FormArray(
  this.numArray.map(_=>(new FormGroup({
     clientName:new FormControl(null),
     quantity:new FormControl(0),
     price::new FormControl(0)
  })))
)

removeItem(index:number) {
  this.formArray.removeAt(index)
}

看起來你對 Angular 服務並不熟悉,所以這里有一個例子來告訴你它是如何工作的。

Stackblitz: https ://stackblitz.com/edit/angular-ivy-afppeb?file=src/app/item.service.ts


這是一個保存項目的簡單服務,它具有添加和刪除方法

物品服務

@Injectable({ providedIn: 'root' })
export class ItemService {
  itemList: Item[] = [];

  addItem(item: Item) {
    this.itemList.push(item);
  }

  deleteItem(index: number) {
    this.itemList.splice(index, 1);
  }
}

要訪問此服務,您只需通過任何組件的構造函數注入它:

添加發票組件

export class AddInvoiceComponent {
  constructor(private itemService: ItemService) {}

  get items() {
    return this.itemService.itemList;
  }

  delete(index: number) {
    this.itemService.deleteItem(index);
  }
}
<app-item-input></app-item-input>
<h1>Items</h1>
<ng-container *ngFor="let item of items; index as i">
  <pre>{{ item | json }}</pre>
  <button (click)="delete(i)">Delete</button>
</ng-container>

這是將表單數據轉換為對象的簡單方法

項目輸入組件

export class ItemInputComponent {
  formGroup = new FormGroup({
    itemName: new FormControl(''),
    quantity: new FormControl(0),
    price: new FormControl(0),
  });

  constructor(private itemService: ItemService) {}

  onSubmit() {
    this.itemService.addItem(this.formGroup.getRawValue());
  }
}
<h1>Input</h1>
<form [formGroup]="formGroup" (ngSubmit)="onSubmit()">
  <div>
    <label>Item Name:</label>
    <input type="text" formControlName="itemName" />
  </div>
  <div>
    <label>Quantity:</label>
    <input type="number" formControlName="quantity" />
  </div>
  <div>
    <label>Price:</label>
    <input type="number" formControlName="price" />
  </div>
  <button type="submit">Submit</button>
</form>

您可能還想進行表單驗證,但這只是為了向您展示服務是如何工作的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM