我正在使用Angular 6构建应用程序,但我对反应式表单有疑问。我正在学习Angular。我有一个表格的所有行的表格,其中有一个要验证的输入是PRODUCT_QUANTITY。输入的数字发生更改时,它将提交表单以使用新值更新表。问题是当我专注于元素并且不更改值时,将为表的所有行激活验证程序错误。我希望仅在未设置数量的情况下对相关行进行激活。对不起,如果我的代码不完美。 您能帮我解决这个问题吗?谢谢
这是代码:
tables.component.html
<mat-form-field>
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
<ng-container>
<mat-form-field>
<mat-select placeholder="Filter par type de produit"
multiple (selectionChange)="displayData($event.value)"
[(ngModel)]="selectedProductsId"
#productIdSelect="ngModel">
<button
mat-raised-button
class="mat-warn fill text-sm"
(click)="emptyFilter(productIdSelect,ids)">
Supprimer filtre
</button>
<mat-option *ngFor="let product of productListType" [value]="product.PRODUCTS_id">{{product.PRODUCTS_title}}</mat-option>
</mat-select>
</mat-form-field>
</ng-container>
<div class="mat-elevation-z8">
<form [formGroup]="form" (submit)="addProductToList()">
<table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="PRODUCT_name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Nom du produit</th>
<td mat-cell *matCellDef="let row"> {{row.PRODUCT_name}} </td>
</ng-container>
<ng-container matColumnDef="PRODUIT_TYPE">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Type de produit</th>
<td mat-cell *matCellDef="let row"> {{row.PRODUIT_TYPE}}</td>
</ng-container>
<ng-container matColumnDef="PRODUCT_QUANTITY">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Quantité</th>
<td mat-cell *matCellDef="let row">
<mat-form-field style="width: 50%">
<input (change)="setIdProduct(row.PRODUCT_id)" formControlName="quantity" matInput min="0" type="number" placeholder="Quantité" value="{{row.PRODUCT_QUANTITY}}">
</mat-form-field>
</td>
</ng-container>
<ng-container matColumnDef="PRODUCT_COMMENT">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Commentaire</th>
<td mat-cell *matCellDef="let row">
<mat-form-field style="width: 60%">
<textarea (change)="setIdProduct(row.PRODUCT_id)" formControlName="remark" matInput placeholder="Ajouter un commentaire"
value="{{row.PRODUCT_COMMENT}}"></textarea>
</mat-form-field>
</td>
</ng-container>
<ng-container matColumnDef="VALIDATE">
<th style="display: none" mat-header-cell *matHeaderCellDef mat-sort-header>Ajouter un produit</th>
<td mat-cell *matCellDef="let row">
<button id="submitForProduct" style="display: none;" mat-raised-button color="primary" type="submit">Ajouter à ma liste de
course
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</form>
<mat-paginator [pageSize]="10" [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
</div>
tables.component.ts
import {Component, OnInit, ViewChild} from '@angular/core';
import {MatPaginator, MatSnackBar, MatSort, MatTableDataSource} from '@angular/material';
import {ProductService} from '../../services/product.service';
import {Product} from '../../models/product';
import {ProductType} from '../../models/producttype';
import {FormBuilder, FormGroup, NgModel, Validators} from '@angular/forms';
import {Subscription} from 'rxjs';
import {forEach} from 'async';
@Component({
selector: 'app-tables',
templateUrl: './tables.component.html',
styleUrls: ['./tables.component.scss']
})
export class TablesComponent implements OnInit {
displayedColumns = ['PRODUCT_name', 'PRODUIT_TYPE', 'PRODUCT_QUANTITY', 'PRODUCT_COMMENT', 'VALIDATE'];
dataSource: MatTableDataSource<Product>;
productListType: ProductType[];
productListItem: Product[] = [];
filteredArray: Product[] = [];
selectedProductsId: ProductType[];
ids: any[] = [];
form: FormGroup;
response: Subscription;
idProduct: number;
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
constructor(private productProvider: ProductService, private addProduct: FormBuilder, private snackBar: MatSnackBar) {
console.log(this.productListItem);
}
ngOnInit() {
this.productProvider.getAllProducts().subscribe(
r => {
this.productListType = r['products'] as ProductType[];
this.productListType.forEach(product => {
this.ids.push(product.PRODUCTS_id);
product.PRODUCTS_products.forEach(productItem => {
this.productListItem.push(new Product(
productItem.PRODUCT_id,
productItem.PRODUCT_name,
productItem.PRODUCT_unit,
product.PRODUCTS_title,
product.PRODUCTS_id,
0,
''));
});
});
this.productProvider.getProductsHousehold(1).subscribe(
result => {
this.productListItem.map(productItem => {
result.products.map(productItemR => {
if (productItemR.PRODUCTS_LIST_id_prod === productItem.PRODUCT_id) {
console.log(productItemR.PRODUCTS_LIST_QUANTITY);
productItem.PRODUCT_QUANTITY = productItemR.PRODUCTS_LIST_quantity;
productItem.PRODUCT_COMMENT = productItemR.PRODUCTS_LIST_remark;
}
});
});
console.log(this.productListItem)
});
this.dataSource = new MatTableDataSource<Product>(this.productListItem);
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
});
this.form = this.addProduct.group({
quantity: ['', [Validators.required]],
remark: ['']
});
}
// filter the list of products
applyFilter(filterValue: string) {
filterValue = filterValue.trim(); // Remove whitespace
filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches
this.dataSource.filter = filterValue;
if (this.dataSource.paginator) {
this.dataSource.paginator.firstPage();
}
}
//Display data when filter changed
displayData(event) {
let array: any;
array = event;
if (array.length === 0) {
array = this.ids;
}
console.log(array);
this.filteredArray = [];
this.productListType.forEach(product => {
array.forEach(productId => {
if (product.PRODUCTS_id === productId) {
product.PRODUCTS_products.forEach(pro => {
this.filteredArray.push(new Product(
pro.PRODUCT_id,
pro.PRODUCT_name,
pro.PRODUCT_unit,
product.PRODUCTS_title,
product.PRODUCTS_id,
pro.PRODUCT_QUANTITY,
pro.PRODUCT_COMMENT));
});
}
});
});
this.dataSource = new MatTableDataSource<Product>(this.filteredArray);
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
}
//empty the filter
emptyFilter(select
:
NgModel, values
) {
select.update.emit([]);
this.displayData([]);
}
//set Id Product and trigger event submit
setIdProduct(PRODUCT_id
:
number
) {
this.idProduct = PRODUCT_id;
console.log(this.idProduct);
document.getElementById('submitForProduct').click();
}
// function called when the form is submitted
addProductToList() {
if (this.form.invalid || this.idProduct < 0) {
this.snackBar.open('Veuillez renseigner tous les champs', '', {
duration: 2000
});
return;
}
const quantity = this.form.controls.quantity.value;
const remark = this.form.controls.remark.value;
this.response = this.productProvider.addProductToList(this.idProduct, 1, quantity, remark).subscribe(
result => {
if (result === true) {
this.snackBar.open('Le produit a bien été ajouté à la liste', '', {
duration: 2000
});
} else {
this.snackBar.open('Produit non ajouté à la liste', '', {
duration: 2000
});
}
});
}
}