angular

Angular 2 update ngFor for one form control


I have a repeating form OrderLines, which has two dropdowns; ProductType and Product. As there are 1000+ products I want to filter the Products in the Product dropdown after selecting / changing a ProductType.

For this I use a productFilter pipe, and on form load this works fine. Although when changing the ProductType it seems the ngFor does not refresh the available values.

<div class="form-group row">
    <label for="product_type_id-field" class="col-md-4 col-form-label">
        Product Type
    </label>
    <div class="col-md-8">
        <select formControlName="product_type_id" class="form-control" id="product_type_id-field">
            <option *ngFor="let productType of productTypes" value="{{productType.id}}">{{productType.name}}</option>
        </select>
    </div>
</div>

<div class="form-group row">
    <label for="product_id-field" class="col-md-4 col-form-label">
        Product
    </label>
    <div class="col-md-8">
        <select formControlName="product_id" class="form-control" id="product_id-field">
            <option *ngFor="let product of products | productFilter: myForm.controls.orderlines.controls[i].controls.product_type_id.value" value="{{product.id}}">{{product.name}}</option>
        </select>
    </div>
</div>

How can I force to refresh the Product dropdown values without initiating the entire form?


Solution

  • The problem seems to be the way you obtain the value of the "product type" field to pass to the productFilter.

    Here's a Plunkr that shows an implementation: https://plnkr.co/edit/b5FKSp06XMfQul5pYQti?p=preview

    I included two techniques for refreshing the product list:

    1. By recalculating the product list for every (change) event on the product type.
    2. By using a custom pipe like you did (my preferred option).

    As you can see, my code is pretty similar to yours. Here's the highlight:

    <select formControlName="product2">
      <option>Pick a product...</option>
      <option *ngFor="let p of allProducts|productFilter:productForm.get('productType').value">{{p.name}}</option>
    </select>
    

    Only notable difference is how I access the productType value (but your form seems more complex). Maybe it'll work if you can fix that bit.

    You can see the code for the rest of the form and the productFilter in the Plunkr.