You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular表单提交函数仅生效一次问题求助

商品搜索表单无法多次提交的问题解决

问题背景

我开发了一款商品搜索应用,表单包含多个字段,提交时调用searchProducts()函数,将表单字段作为请求参数向API发送GET请求。

  • 问题:表单仅能生效1-2次,之后必须刷新页面才能再次搜索,不清楚原因。
  • 需求:无需刷新页面,每次提交表单时都能调用searchProducts()函数,支持用户多次搜索。

核心代码

组件TypeScript代码

export class SearchproductComponent implements OnInit {

  isAuthenticated(){
    return this.userService.isAuthenticated();
  }

  productSearchForm = this.fb.group({
    productCode: [, []],
    name: [, []],
    brand: [, []],
    priceLow: [,[]],
    priceHigh: [, []]
  })

  get productCode(){
    return this.productSearchForm.get('productCode');
  }

  get name(){
    return this.productSearchForm.get('name');
  }

  get brand(){
    return this.productSearchForm.get('brand');
  }

  constructor(private fb: FormBuilder, public productsService: ProductsService, public userService: UserserviceService) { }

  ngOnInit(): void {
  }

  searchProducts(){
    let name = this.productSearchForm.controls.name.value!
    let brand = this.productSearchForm.controls.brand.value!
    let productCode = this.productSearchForm.controls.productCode.value!

    if (name && brand === null && productCode === null){
      let response = this.productsService.getProductsByName(name)
      console.log(response)
    }
    if (name && brand && productCode === null){
      let response = this.productsService.getProductsByNameAndBrand(name, brand)
      console.log(response)
      console.log("Name and Brand Working");
    }
    if (name && brand && productCode){
      let response = this.productsService.getProductsByNameAndBrandAndProductCode(name, brand, productCode)
      console.log(response)
      console.log("Name and Brand and Product Code Working")
    } 
  }
}

表单HTML代码

<div class="search-form">
    <form (ngSubmit)="searchProducts()" [formGroup]="productSearchForm" name="productSearch" class="form-inline">
        <div class="row">
            <div class="col-4">
                <div class="mb-3">
                    <label for="product-code" class="form-label">Product Code: </label>
                    <input type="text" class="form-control" id="product-code" name="product-code" formControlName="productCode">
                </div>
            </div>
            <div class="col-4">
                <div class="mb-3">
                <label for="name" class="form-label">Name: </label>
                <input type="text" class="form-control" id="name" name="name" formControlName="name">
                </div>
            </div>
            <div class="col-4">
            <div class="mb-3">
                <label for="brand" class="form-label">Brand: </label>
                <input type="text" class="form-control" id="brand" name="brand" formControlName="brand">
            </div></div>
            
        </div>
        <div class="row">
            <div class="col-2 mb-3">
                <button type="submit" class="btn btn-primary mb-3">Search</button>
                <button type="button" class="btn btn-warning" (click)="filterAnother()">Search Another</button>

            </div>
           
            <div class="col-10 mb-3" *ngIf="isAuthenticated();">
                <div class="row">
                    <div class="col-2">
                        
                    </div>
                    <div class="col-2">
                        <button type="button" class="btn btn-success mb-3" (click)="filterByPrice()">Filter by Price</button>

                        <button type="button" class="btn btn-primary" (click)="filterAnother()">Filter Another</button>
                    </div>
                    <div class="col-2 mu-2">
                        <label for="price-range" class="form-label price-range-label">Price Range: </label>
                    </div>
                    <div class="col-3">
                        <input type="text" class="form-control" id="price-range-low" name="price-low" formControlName="priceLow">
                    </div>
                    <div class="col-3">
                        <input type="text" class="form-control" id="price-range-high" name="price-high" formControlName="priceHigh">
                    </div>
                </div>
            </div>
        </div>
    </form>
</div>

界面展示

商品搜索UI

修复方案

1. 正确处理Observable订阅

服务的getProductsByName等方法返回的是Observable,仅获取对象不会触发HTTP请求,未订阅还可能导致状态异常。修改searchProducts中的服务调用逻辑,添加订阅并处理结果:

searchProducts(){
  let name = this.productSearchForm.controls.name.value ?? '';
  let brand = this.productSearchForm.controls.brand.value ?? '';
  let productCode = this.productSearchForm.controls.productCode.value ?? '';

  if (name && !brand && !productCode){
    this.productsService.getProductsByName(name).subscribe({
      next: (response) => {
        console.log(response);
        // 在此处处理搜索结果,比如赋值给用于展示的变量
      },
      error: (err) => console.error('搜索失败:', err)
    });
  }
  if (name && brand && !productCode){
    this.productsService.getProductsByNameAndBrand(name, brand).subscribe({
      next: (response) => {
        console.log(response);
        console.log("Name and Brand Working");
      },
      error: (err) => console.error('搜索失败:', err)
    });
  }
  if (name && brand && productCode){
    this.productsService.getProductsByNameAndBrandAndProductCode(name, brand, productCode).subscribe({
      next: (response) => {
        console.log(response);
        console.log("Name and Brand and Product Code Working");
      },
      error: (err) => console.error('搜索失败:', err)
    });
  }
}

2. 修复表单初始化与条件判断

表单字段未设置默认值会导致空值为undefined,原条件判断=== null无法匹配。修改表单初始化,设置默认值为null:

productSearchForm = this.fb.group({
  productCode: [null, []],
  name: [null, []],
  brand: [null, []],
  priceLow: [null, []],
  priceHigh: [null, []]
});

3. 重置表单状态(可选)

多次提交后,表单可能进入脏状态或无效状态,可在搜索完成后重置表单状态(根据需求选择是否清空输入值):

// 在searchProducts函数末尾添加
// 仅重置状态,保留用户输入
this.productSearchForm.markAsPristine();
this.productSearchForm.markAsUntouched();

// 如果需要清空输入值,使用reset
// this.productSearchForm.reset();

内容的提问来源于stack exchange,提问作者Innomight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 10:16:10