将 JSON 响应分配给 mat-autocomplete
Assigning JSON response to mat-autocomplete
我有一个与下面组件中的选项变量一起使用的自动完成功能,但我无法让它指向 JSON 对象 this.posts
中有一个字段 this.posts 称为 artistName,我正在尝试 return 作为自动完成列表。如果我尝试将 this.posts 分配给
<mat-option *ngFor="let option of this.posts| async" [value]="option">
{{option}}
</mat-option>
这是不允许的。我不明白如何从 JSON 响应中获取我的结果以显示在自动完成中。我意识到 this.posts 是一个对象,我正在寻找特定字段 artistName,但我想我不知道如何正确连接它。感谢您的帮助
示例输入和 return(arti 是键入的值)
arti
[ { _id: 5e20c5a139a92512cc7df63c, artistName: 'artist' }, {
_id: 5e2350c7f88cfb331c4f67de, artistName: 'artist1' } ]
组件
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
);
}
}
html
<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>
您无法访问 .html 文件中的 this
运算符。
替换 ,
<mat-option *ngFor="let option of this.posts| async" [value]="option">
{{option}}
</mat-option>
由
<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>
如果
posts = [ { _id: 5e20c5a139a92512cc7df63c, artistName: 'artist' }, {
_id: 5e2350c7f88cfb331c4f67de, artistName: 'artist1' } ]
然后
<mat-option *ngFor="let option of posts" [value]="option"> //remove this from this.posts
{{option.artistName}}
</mat-option>
posts: Listing[] = [];
帖子不可观察,使用
<mat-option *ngFor="let option of posts" [value]="option">
{{option.artistName}}
</mat-option>
不要在模板中使用 this
引用 TypeScript 变量(它是隐式的)。此外,您的 posts
属性 不是 Observable
,因此您不需要 async
管道。最后一件事,你的 option
变量引用了一个 Listing
,它有 _id
和 artistName
属性,所以你必须将它们正确设置到 [value]
和插值显示文字。
另一个对解决方案没有影响的细节(只是清洁问题):在你的"wait for the user to stop typing"实现中,使用箭头函数,然后你可以引用this
而不保留引用用 var $this = this;
您的 HTML 应该是:
<mat-option *ngFor="let post of posts" [value]="post._id">
{{post.artistName}}
</mat-option>
您的 onKeySearch
函数可以是:
private onKeySearch(event: any) {
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
if (event.keyCode !== 13) {
this.executeListing(event.target.value);
}
}, 1000);
}
我有一个与下面组件中的选项变量一起使用的自动完成功能,但我无法让它指向 JSON 对象 this.posts
中有一个字段 this.posts 称为 artistName,我正在尝试 return 作为自动完成列表。如果我尝试将 this.posts 分配给
<mat-option *ngFor="let option of this.posts| async" [value]="option">
{{option}}
</mat-option>
这是不允许的。我不明白如何从 JSON 响应中获取我的结果以显示在自动完成中。我意识到 this.posts 是一个对象,我正在寻找特定字段 artistName,但我想我不知道如何正确连接它。感谢您的帮助
示例输入和 return(arti 是键入的值)
arti
[ { _id: 5e20c5a139a92512cc7df63c, artistName: 'artist' }, {
_id: 5e2350c7f88cfb331c4f67de, artistName: 'artist1' } ]
组件
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
);
}
}
html
<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>
您无法访问 .html 文件中的 this
运算符。
替换 ,
<mat-option *ngFor="let option of this.posts| async" [value]="option">
{{option}}
</mat-option>
由
<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>
如果
posts = [ { _id: 5e20c5a139a92512cc7df63c, artistName: 'artist' }, {
_id: 5e2350c7f88cfb331c4f67de, artistName: 'artist1' } ]
然后
<mat-option *ngFor="let option of posts" [value]="option"> //remove this from this.posts
{{option.artistName}}
</mat-option>
posts: Listing[] = [];
帖子不可观察,使用
<mat-option *ngFor="let option of posts" [value]="option">
{{option.artistName}}
</mat-option>
不要在模板中使用 this
引用 TypeScript 变量(它是隐式的)。此外,您的 posts
属性 不是 Observable
,因此您不需要 async
管道。最后一件事,你的 option
变量引用了一个 Listing
,它有 _id
和 artistName
属性,所以你必须将它们正确设置到 [value]
和插值显示文字。
另一个对解决方案没有影响的细节(只是清洁问题):在你的"wait for the user to stop typing"实现中,使用箭头函数,然后你可以引用this
而不保留引用用 var $this = this;
您的 HTML 应该是:
<mat-option *ngFor="let post of posts" [value]="post._id">
{{post.artistName}}
</mat-option>
您的 onKeySearch
函数可以是:
private onKeySearch(event: any) {
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
if (event.keyCode !== 13) {
this.executeListing(event.target.value);
}
}, 1000);
}