Как правильно использовать mat-autocomplete с удаленными данными graphQL? - PullRequest
0 голосов
/ 09 сентября 2018

Я использую Angular 6 здесь с угловым материалом, и я пытаюсь создать поисковый компонент, который использует graphQL с Apollo.

хорошо, компонент работает, но я хотел бы решить эти проблемы:

  1. Я хочу добавить debounceTime и не могу точно найти, где его добавить.
  2. Я хочу, чтобы пустые значения не были найдены в запросе graphQL
  3. Я не использую асинхронный фильтр для автозаполнения матов, так как я помещаю результаты в массив.это правильный путь?

Мой сервис продуктов, который взаимодействует с сервером GraphQL:

import { Injectable } from '@angular/core';
import {Apollo} from 'apollo-angular';
import gql from 'graphql-tag';

@Injectable({
  providedIn: 'root'
})
export class ProductService {

  constructor(private apollo: Apollo) { }

  searchForProduct(productName: string) {
    return this.apollo.watchQuery<any>({
    query: gql`{products_by_p_name_search(lang_id:1,query:"${productName}")
    {category_id,price,category_name,id,name,desc,quantity,year_manufacture,image_file}}`
    });
  }
}

мой поисковый компонент html с компонентом mat-autocomplete:

<form class="example-form">
  <mat-form-field class="example-full-width">
    <input matInput placeholder="חפש מוצר" aria-label="חפש מוצר" [matAutocomplete]="auto" [formControl]="productCtrl">
    <mat-autocomplete #auto="matAutocomplete">
      <mat-option *ngFor="let product of products" [value]="product.name">
        <img class="example-option-img" aria-hidden src="../../assets/products/{{product.id}}/{{product.imgFile}}_t.jpg" height="25">
        <span>{{product.name}}</span> |
        <small>Population: {{product.population}}</small>
      </mat-option>
    </mat-autocomplete>
  </mat-form-field>
</form>

И, наконец, мой компонент поиска (файл Typescript):

import { Component, OnInit } from '@angular/core';
import {FormControl} from '@angular/forms';
import {Product} from '../product';
import {ProductService} from '../product.service';

@Component({
  selector: 'app-search-product',
  templateUrl: './search-product.component.html',
  styleUrls: ['./search-product.component.scss']
})
export class SearchProductComponent implements OnInit {
  productCtrl = new FormControl();
  products: Product[] = [];

  constructor(private productService: ProductService) {

  }


  ngOnInit() {
    this.productCtrl.valueChanges
      .subscribe(v => {
        this.productService.searchForProduct(v.toString()).valueChanges.subscribe(
          ({data}) => {
            const productsResult: Product[] = [];
            data.products_by_p_name_search.forEach((productObj) => {
                const product = new Product();
                product.id = productObj.id;
                product.categoryName = productObj.category_name;
                product.name = productObj.name;
                product.desc = productObj.desc;
                product.quantity = productObj.quantity;
                product.yearManufacture = productObj.year_manufacture;
                product.imgFile = productObj.image_file;
                product.categoryId = productObj.category_id;
                product.price = productObj.price;
                productsResult.push(product);
              });
            this.products = productsResult;
          });
      });
  }
}

Насколько я вижу, эти строки кода могут работать, но это может быть не самый оптимизированный способ написания,поэтому любая информация по вышеуказанным вопросам будет принята с благодарностью.

1 Ответ

0 голосов
/ 14 сентября 2018

Я хочу добавить debounceTime и не могу найти, где именно его добавить.

Вы добавляете время отката [ 1 ], где вы подписываетесь на обновления стоимости. Ваш ngOnInit будет выглядеть примерно так

ngOnInit() {
this.productCtrl.valueChanges
  .pipe(
    debounceTime(500),
    distinctUntilChanged()
  )
  .subscribe(v => {
  ...

Не забудьте import {debounceTime} from 'rxjs/operators';.

Я хочу, чтобы пустые значения не были найдены в запросе graphQL

бросить filter( value => value.length > 0)

Ваш ngOnInit теперь похож на

ngOnInit() {
  this.productCtrl.valueChanges
    .pipe(
      debounceTime(500),
      distinctUntilChanged(),
      filter( value => value.length > 0)
    )
    .subscribe(v => {
 ...

Я не использую асинхронный фильтр для автозаполнения, так как результаты помещаются в массив. это правильный путь?

Я не знаю, почему вы не используете асинхронную трубу. Этот SO-ответ содержит рабочую демонстрацию трубы.

...