Мат автозаполнения не фильтрует значения - PullRequest
0 голосов
/ 24 января 2020

У меня есть список продуктов, для которых мне хотелось бы иметь функцию автозаполнения при выборе, но, похоже, это не работает так, как я пытаюсь. Любая помощь будет высоко оценена в этом отношении. Заранее спасибо

вот мой html код

form [formGroup]="loanProductForm">
<table style="overflow-x: auto;display: inline-block; white-space: nowrap;">
    <thead>
        <tr class='tableHeader'>
            <div fxLayout="row" fxLayoutAlign="start center" fxFlex="1 0 auto">
                <td fxFlex="14" class="pr-4">Name</td>
                <td fxFlex="14" class="pr-4">Price</td>
                <td fxFlex="14" class="pr-4">Loan Term</td>
                <td fxFlex="14" class="pr-4">Quantity</td>
                <td fxFlex="14" class="pr-4">Deposit</td>
                <td fxFlex="14" class="pr-4">Total</td>
                <td fxFlex="14" class="pr-4">Action</td>
            </div>
        </tr>
    </thead>
    <tbody>
        <tr formArrayName="products" *ngFor="let product of loanProductForm.get('products').controls; let i = index">
            <div [formGroupName]="i" fxLayout="row" fxLayoutAlign="start center" fxFlex="1 0 auto">
                <td fxFlex="14">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Product </mat-label>

                        <input type="text" placeholder="Product" name="" formControlName="product" matInput
                            [matAutocomplete]="productauto">

                        <mat-autocomplete autoActiveFirstOption (selectionChange)="onChangedProduct($event, i)"
                            [id]="'product.productId' + i" #productauto="matAutocomplete" [displayWith]="displayFn">
                            <mat-option *ngFor="let product of filteredProducts | async" [value]="product">
                                {{product.name}}
                            </mat-option>
                        </mat-autocomplete>

                        <!-- <mat-select formControlName="productId" (selectionChange)="onChangedProduct($event, i)" [id]="'productId' + i" required>
                                                        <mat-option *ngFor="let product of productList" [value]="product.productId">
                                                            {{product.name}}
                                                        </mat-option>
                                                    </mat-select> -->

                    </mat-form-field>
                </td>
                <td fxFlex="14">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Price </mat-label>
                        <input type='number' (keyup)="onPriceChange($event)" matInput formControlName="price"
                            [id]="'price' + i" name="" placeholder="Price" required>
                    </mat-form-field>
                </td>
                <td fxFlex="14">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Loan Term </mat-label>
                        <mat-select formControlName="loanTermId" [id]="'loanTermId' + i" required>
                            <mat-option *ngFor="let loanTerm of loanTermList" [value]="loanTerm.loanTermId">
                                {{loanTerm.numberOfMonths}}
                            </mat-option>
                        </mat-select>
                    </mat-form-field>
                </td>
                <td fxFlex="14">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Quantity </mat-label>
                        <input type='number' min="1" formControlName="quantity" [id]="'quantity' + i" matInput name=""
                            id="" placeholder="Quantity" required>

                    </mat-form-field>
                </td>
                <td fxFlex="14">
                    <mat-form-field appearance="outline" fxFlex="100" class="pr-4">
                        <mat-label>Deposit </mat-label>
                        <input type='number' min="1" formControlName="deposit" [id]="'deposit' + i" matInput name=""
                            id="" placeholder="Deposit" required>
                    </mat-form-field>
                </td>
                <td fxFlex="14">
                    <div fxFlex="100" class="pr-4">
                        <mat-label>KES:&nbsp;&nbsp;</mat-label>
                        <input [disabled]="true" formControlName="total" [id]="'total' + i" matInput name="total"
                            class='total' id="" placeholder="Total" style="color:black; font-weight:bold; width: unset;"
                            required>
                    </div>
                </td>
                <td fxFlex="14">
                    <div fxFlex="100" class="pr-4">
                        <!-- <button class='deleteButton' mat-stroked-button style="color:red" > -->
                        <span class='deleteButton' (click)='deleteProduct(i)'>
                            <mat-icon>delete</mat-icon>
                        </span>
                        <!-- </button> -->
                    </div>
                </td>

            </div>
        </tr>
        <tr>
            <td fxFlex="10">
                <div fxLayout="row" fxLayoutAlign="start center" fxFlex="1 0 auto">
                    <button type="button" mat-stroked-button class='addBtn btn-style-2' fxFlex='100'
                        (click)='addProductButtonClick()'>Add
                        <mat-icon>add_box</mat-icon>
                    </button>
                </div>
            </td>
        </tr>
    </tbody>
</table>
</form>

и вот код компонента

filteredProducts: Observable<string[]>;
productList: any;

addProductFormGroup(): FormGroup {
    return this._formBuilder.group({
        productId: ['', Validators.required],
        product: [''],
        price: [0, Validators.required],
        loanTermId: ['', Validators.required],
        quantity: [0, Validators.required],
        deposit: [0, Validators.required],
        total: [0, Validators.required],
    });
}
ngOnInit() {
    this.getProducts();

    this.loanProductForm = this._formBuilder.group({
        products: this._formBuilder.array([
            this.addProductFormGroup()
        ]),
        product: ['']
    });
    this.loanProductForm.valueChanges.pipe(debounceTime(20)).subscribe((values) => {

        (this.loanProductForm.get('products') as FormArray).controls.forEach(group => {
            let total = (group.get('quantity').value * group.get('price').value) - group.get('deposit').value;
            group.get('total').setValue(total);
            // group.get('total').setValue(this.currencyPipe.transform(total, 'KES '));
        });

    }
getProducts() {
        this.productService.getProducts().subscribe((response) => {
            this.productList = response;
            this.productList.sort((a, b) => (a.productId < b.productId) ? 1 : -1);

            this.filteredProducts = this.loanProductForm.get('product').valueChanges.pipe(
                startWith(''),
                map(value => typeof value === 'string' ? value : value.name),
                map(value => this.productFilter(value))
            );
        });

    }
  private productFilter(product) {
        console.log('value: ', product);
        const filterValue = product.toLowerCase();
        return this.productList.filter(product => product.name.toLowerCase().indexOf(filterValue) === 0);
    }
    addProductButtonClick(): void {

        (<FormArray>this.loanProductForm.get('products')).push(this.addProductFormGroup());
    console.log('Loan Products: ', this.loanProductForm.value);

}

Я набрал его, но его без фильтрации значений Ниже приведено изображение, как выглядит моя форма Image for better understanding

Ответы [ 2 ]

3 голосов
/ 24 января 2020

Я недавно работал над функцией автозаполнения (mat-autocomplete) самостоятельно. Сначала у меня была такая же проблема, но через несколько часов я заработал.

Я нашел этот пример . У меня это сработало (после изменения formControlName на formControl)

<form class="example-form">
  <mat-form-field class="example-full-width">
    <input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [matAutocomplete]="auto">
    <mat-autocomplete #auto="matAutocomplete">
      <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
        {{option}}
      </mat-option>
    </mat-autocomplete>
  </mat-form-field>
</form>
1 голос
/ 24 января 2020

Вы должны связать каждый продукт элемент управления внутри FormArray с FilterOption массивом

 ManageProductControl(index: number) {
    var arrayControl = this.myForm.get('items') as FormArray;
    this.filteredOptions[index] = arrayControl.at(index).get('product').valueChanges
      .pipe(
      startWith<string | User>(''),
      map(value => typeof value === 'string' ? value : value.name),
      map(name => name ? this._filter(name) : this.options.slice())
      );

  }

Затем после каждого построения formgroup внутри массива формы (создайте новый элемент), мне нужно вызвать указанную выше функцию с новым индексом, например так:

addNewItem() {
    const controls = <FormArray>this.myForm.controls['items'];
    let formGroup = this.formBuilder.group({
      product: ['', [Validators.required]],
      price: ['', [Validators.required]],
    });
    controls.push(formGroup);    
    this.ManageProductControl(controls.length - 1);
  }

В файле. html вам нужно чтобы обратиться к нужному массиву FilterOption, мы можем сделать это, используя индекс i:

<mat-option *ngFor="let option of filteredOptions[i] | async " [value]="option">
  {{ option.name }}
</mat-option>

Вот для него stackblitz

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...