0
votes

Attribution d'une réponse JSON à mat-autocomplete

J'ai une saisie semi-automatique qui fonctionne avec la variable d'options dans le composant ci-dessous, mais je ne peux pas la faire pointer vers l'objet JSON this.posts Il y a un champ dans ceci. messages appelés artistName que j'essaie de renvoyer sous forme de liste à saisie semi-automatique. Si j'essaye d'attribuer le this.posts à

   <form class="example-form">
          <mat-form-field class="searchField" [ngStyle]="{'font-size.px': 12}" appearance="outline">
            <mat-label id="placeholder">Find Artist</mat-label>
            <input type="text" placeholder="Pick one" name="artistName" aria-label="Number" matInput
              [formControl]="myControl" (keyup)="onKeySearch($event)" [matAutocomplete]="auto">
            <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
              <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
                {{option}}
              </mat-option>
            </mat-autocomplete>
          </mat-form-field>
        </form>


ce n'est pas autorisé. Je ne comprends pas comment faire apparaître mes résultats de la réponse JSON dans la saisie semi-automatique. Je me rends compte que this.posts est un objet et je recherche le champ spécifique artistName, mais je suppose que je ne peux pas comprendre comment le câbler correctement. J'apprécie toute aide

exemple d'entrée et de retour (arti est une valeur saisie)

  import {
  Component,
  HostListener,
  OnDestroy,
  OnInit,
  Input,
  AfterViewInit
} from "@angular/core";
import { AuthService } from "../auth.service";
import { Router } from "@angular/router";
import { SearchService } from "./search.service";
import { DeviceDetectorService } from "ngx-device-detector";
import { Subject } from "rxjs";
import { takeUntil, startWith, map } from "rxjs/operators";

import { Store } from "@ngrx/store";
import { Observable } from "rxjs";
import { SubmitListingService } from "../submit-listing/submit-auction.service";
import { Listing } from "../submit-listing/listing.model";
import { FormControl } from "@angular/forms";

interface AppState {
  message: string;
}
@Component({
  selector: "app-header",
  templateUrl: "./header.component.html",
  styleUrls: ["./header.component.css"]
})
export class HeaderComponent implements OnInit, OnDestroy, AfterViewInit {
  message: string;
  destroy = new Subject();
  userIsAuthenticated = false;
  searchField: string;
  posts: Listing[] = [];
  mobile: boolean;
  userId: string;
  test: string;
  isValid = false;
  message$: Observable<string>;
  timeout: any = null;
  isOpen = false;
  myControl = new FormControl();
  options: string[] = ["One", "Two", "Three"];
  filteredOptions: Observable<string[]>;

  constructor(
    private authService: AuthService,
    private searchService: SearchService,
    public router: Router,
    private mobileDetect: DeviceDetectorService,
    private store: Store<AppState>,
    private submitListingService: SubmitListingService
  ) {
    this.message$ = this.store.select("message");
  }

  click() {
    if (!this.isOpen) {
      this.store.dispatch({ type: "true" });
      this.isOpen = true;
    } else if (this.isOpen) {
      this.store.dispatch({ type: "false" });
      this.isOpen = false;
    }
  }

  onLogout() {
    this.authService.logout();
  }

  hideLogoutButton() {
    if (
      (this.userIsAuthenticated &&
        !this.mobile &&
        this.router.url !== "/listings") ||
      (this.userIsAuthenticated &&
        !this.mobile &&
        this.router.url === "/listings")
    ) {
      return true;
    } else {
      return false;
    }
  }
  ngAfterViewInit() {}

  ngOnInit() {
    this.mobile = this.mobileDetect.isMobile();
    this.userId = this.authService.getUserId();
    this.test = this.router.url;
    this.userIsAuthenticated = this.authService.getIsAuth();
    this.authService
      .getAuthStatusListener()
      .pipe(takeUntil(this.destroy))
      .subscribe(isAuthenticated => {
        this.userIsAuthenticated = isAuthenticated;
      });

    this.searchService.currentMessage
      .pipe(takeUntil(this.destroy))
      .subscribe(message => (this.message = message));

    this.filteredOptions = this.myControl.valueChanges.pipe(
      startWith(""),
      map(value => this._filter(value))
    );

    console.log(this.filteredOptions);
  }
  private onKeySearch(event: any) {
    clearTimeout(this.timeout);
    var $this = this;
    this.timeout = setTimeout(function() {
      if (event.keyCode !== 13) {
        $this.executeListing(event.target.value);
      }
    }, 1000);
  }

  private executeListing(artistName: string) {
    if (artistName.length > 3) {
      //  alert(artistName);
      this.submitListingService.getArtistId(artistName).subscribe(res => {
        console.log("res");
        console.log(res);
        this.posts = res.posts;
        console.log(this.posts);
      });
    }
  }
  ngOnDestroy() {
    this.destroy.next();
    this.destroy.complete();
  }
  private _filter(value: string): string[] {
    const filterValue = value.toLowerCase();

    return this.options.filter(
      option => option.toLowerCase().indexOf(filterValue) === 0
    );
  }
}

composant

     arti
     [ { _id: 5e20c5a139a92512cc7df63c, artistName: 'artist' },   {
         _id: 5e2350c7f88cfb331c4f67de, artistName: 'artist1' } ]

html

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


0 commentaires

3 Réponses :


1
votes

Vous ne pouvez pas accéder à cet opérateur dans le fichier .html .

Remplacer ,

<mat-option *ngFor="let option of posts" [value]="option"> //remove this from this.posts
                    {{option.artistName}}
                  </mat-option>

posts = [ { _id: 5e20c5a139a92512cc7df63c, artistName: 'artist' },   {
         _id: 5e2350c7f88cfb331c4f67de, artistName: 'artist1' } ]

Si

<mat-option *ngFor="let option of posts| async" [value]="option"> //remove this from this.posts
                {{option}} //Here option will the object from the Array posts , therefore you need to provide like {{option.key}} here key will be any key of value you want to display.
              </mat-option>

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


2 commentaires

Si je remplace mon code par votre dernier extrait de code, alors j'obtiens "InvalidPipeArgument: '' for pipe 'AsyncPipe'" "


Supprimez le | async à partir du code et cela fonctionnera. @ user6680



1
votes

posts: Listing [] = []; les messages ne sont pas observables, utilisez

<mat-option *ngFor="let option of posts" [value]="option">
                    {{option.artistName}}
                  </mat-option>


0 commentaires

2
votes

Ne faites pas référence à une variable TypeScript avec this dans le modèle (c'est implicite). De plus, votre propriété posts n'est pas un Observable , vous n'avez donc pas besoin du tube async . Enfin, votre variable option fait référence à une Listing qui a les propriétés _id et artistName , vous devez donc définissez-les correctement dans [valeur] et le texte d'affichage interpolé.

Autre détail qui n'a aucun impact sur la solution (juste une question de propreté): dans votre "attendez que l'utilisateur arrête de taper "implémentation, utilisez une fonction de flèche, alors vous pouvez vous référer à this sans garder une référence dessus avec var $ this = this;

Votre HTML devrait être:

private onKeySearch(event: any) {
    clearTimeout(this.timeout);
    this.timeout = setTimeout(() => {
        if (event.keyCode !== 13) {
            this.executeListing(event.target.value);
        }
    }, 1000);
}

Et votre fonction onKeySearch pourrait être:

<mat-option *ngFor="let post of posts" [value]="post._id">
    {{post.artistName}}
</mat-option>


0 commentaires