Angular router.navigate не будет работать из автозаполнения материала - PullRequest
1 голос
/ 08 июля 2019

Я нахожусь в процессе создания элемента управления автозаполнением для поиска, где я могу искать продукты, и как только кто-то нажимает на один из продуктов, он должен перейти на одну страницу продукта с идентификатором этого продукта в URL.

В моей текущей попытке используется автозаполнение Angular Material (v 7.3.7), и я смоделировал этот пример (https://itnext.io/using-angular-6-material-auto-complete-with-async-data-6d89501c4b79).

). Хотя поисковая часть работает нормально и выбирает продукт, когда я пытаюсь направитьиз метода обратного вызова я получаю сообщение об ошибке. Я подозреваю, что проблема в том, что объект маршрутизатора не виден для автозаполнения, возможно, потому что он находится в FormGroup.

Некоторые примечания:

Сначала, пока яЯ бы хотел, чтобы он в конечном итоге направлялся на страницу продукта. Я упростил маршрут, чтобы просто направить его на домашнюю страницу.

Я ввел маршрутизатор в конструктор и попробовал его с отдельной кнопки тестирования, и онработает нормально. Я пробовал кнопку тестирования как внутри, так и вне FormGroup.

Я также пытался сделать объект маршрутизации общедоступным.

Рабочий код очень близок к учебному примеру, но я покажу, что я могу здесь:

HTML

<form [formGroup]='prodForm'>
  <mat-form-field class="example-full-width">
    <input matInput [matAutocomplete]="auto" formControlName='prodInput'>
  </mat-form-field>

  <mat-autocomplete #auto="matAutocomplete" [displayWith]="navToProd">
    <mat-option *ngIf="isLoading" class="is-loading"><mat-spinner diameter="25"></mat-spinner></mat-option>
    <ng-container *ngIf="!isLoading">
      <mat-option *ngFor="let prod of filteredProds" [value]="prod">
        <img class="example-option-img" [src]="prod.productImage.imagePath" height="35">
        <span>{{ prod.productName }}</span>
        <small> | {{prod.brand.brandName}} | {{prod.category.categoryName}}</small>
      </mat-option>
    </ng-container>
  </mat-autocomplete>

  <div>selected product: {{prodForm.get('prodInput').value | json}}</div>

  <!-- just a test button to see if routing is working outside the control -->
  <button class="btn" (click)="test()">TEST</button>

</form>


И TS

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

import { FormBuilder, FormGroup } from '@angular/forms';
import { switchMap, debounceTime, tap, finalize } from 'rxjs/operators';

import { CatalogService } from '../shared-services/catalog.service';
import { SrfProduct } from '../data-objects/srf-obj-product';

@Component({
  selector: 'app-test-alpha',
  templateUrl: './test-alpha.component.html',
  styleUrls: [
    '../app.component.scss',
    './test-alpha.component.scss'    
  ]
})
export class TestAlphaComponent implements OnInit {

  filteredProds: SrfProduct[] = [];
  prodForm: FormGroup;
  isLoading = false;  

  constructor(
    private router: Router,
    private fb: FormBuilder,
    private catalogService: CatalogService) { }

  ngOnInit() {
    this.prodForm = this.fb.group({
      prodInput: null
    })

    // ===== GET by search term    
    this.prodForm.get('prodInput').valueChanges
      .pipe(
        debounceTime(300),
        tap(() => this.isLoading = true),
          switchMap(value => this.catalogService.getProductsBySearchTerm(value, 0, 10)
          .pipe(
            finalize(() => this.isLoading = false),
          )
        )
      )
      .subscribe(prods => this.filteredProds = prods);

  }

  navToProd(prod: SrfProduct) {
    if (prod) {
      this.router.navigate(['/home']);   // <- this throws the error
      return prod.productName;
    }
  }

  test() {
    this.router.navigate(['/home']);  // <- but this works ok
  }

}

Во всех случаях, когда я маршрутизирую функцию [displayWith]="navToProd", я получаю Невозможно прочитать свойство navigate 'с неопределенной ошибкой.

1 Ответ

0 голосов
/ 08 июля 2019

причина, по которой вы получаете неопределенную ошибку, связана с этим контекстом .когда вы связываете navToProd как входные данные, такие как [displayWith]="navToProd" , этот контекст теряется и выдает неопределенную ошибку.прочитайте немного о этом контексте в событии javascript

, хотя вы исправляете неопределенную ошибку, тем не менее вы используете [displayWith]="navToProd" совершенно неправильно.displayWith используется для сопоставления управляющего значения параметров с отображаемым значением, как объяснено в документах , что означает, что он вычисляет (на основе значения параметра) и возвращает строку для использования в качестве отображаемого текста.это не имеет никакого отношения к выделению.

, если вы хотите предпринять какое-либо действие, когда пользователь выбирает опцию, вы должны использовать optionSelected событие MatAutoComplete

изменить ваш HTMLкодировать следующим образом

<mat-autocomplete #auto="matAutocomplete" (optionSelected)="navToProd($event)">

и модифицировать navToProd метод следующим образом

  navToProd(event: MatAutocompleteSelectedEvent) {
    const prod = event.option.value;
    if (prod) {
      this.router.navigate(['/home']); // change the url according to prod
    }
  }
...