我正在尝试在搜索服务忙于检索和过滤结果时显示微调器。我认为*ngIf
的更新的Angular语法除了if条件之外还允许你有一个else条件。但是每当我开始输入时,微调器都会正确显示,很快就会出现控制台中的错误,抱怨更改检测运行后值会发生变化。
@Component({
selector: 'app-help-search',
templateUrl: './help-search.component.html',
styleUrls: ['./help-search.component.scss'],
providers: [HelpSearchService]
})
export class HelpSearchComponent implements OnInit {
searching: boolean;
helpItems: Observable<HelpItem[]>;
private searchTerms = new Subject<string>();
constructor(
private alertService: AppLevelAlertService,
private helpSearchService: HelpSearchService,
private router: Router) { }
/**
* Push a search term into the observable stream.
*/
search(term: string): void {
this.searching = true;
this.searchTerms.next(term);
}
ngOnInit() {
this.helpItems = this.searchTerms
.debounceTime(300)
.distinctUntilChanged()
.switchMap(term => term
? this.helpSearchService.search(term)
: Observable.of<HelpItem[]>([])
)
.catch(error => {
this.alertService.errorOccurred.emit(new Error(error._body.error));
return Observable.of<HelpItem[]>([]);
})
.finally(() => this.searching = false);
}
gotoHelpItem(helpItem: HelpItem): void {
this.router.navigateByUrl(helpItem.url.toString());
}
}
<div id="search-component">
<div class="form-group">
<label for="search-box">Search for help topics: </label>
<input type="text" #searchBox id="search-box" (keyup)="search(searchBox.value)" style="display: block; width: 100%; font-size: 20pt; height: 25pt" />
</div>
<div *ngIf="searching; then spinner else searchResults"></div>
<ng-template #spinner>
<span class="spinner spinner-lg">
Loading...
</span>
</ng-template>
<ng-template #searchResults>
<div *ngFor="let helpItem of helpItems | async" (click)="gotoHelpItem(helpItem)" class="search-result">
<app-help-item [helpItem]="helpItem"></app-help-item>
</div>
</ng-template>
</div>
我注意到在this.searching
谓词中将false
设置为.finally
是导致此问题的原因。我尝试订阅this.helpItems
并在next
谓词设置this.searching
中订阅false
,而不是这种方法。这会在结果返回时正确删除微调器。但不幸的是,这仍然不起作用,因为for循环不占用微调器的位置。一旦结果回来,ng-templates
都会消失。
答案 0 :(得分:0)
我采用了不同的方法来解决这个问题。我没有使用新的number1.setText("0")
if-then-else条件来决定渲染哪个*ngIf
,而是选择覆盖微调器并使用css来控制其可见性。以下是改进后的方法,对我来说效果很好:
ng-template
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { Router } from '@angular/router';
import { Observable, Subject } from 'rxjs/Rx';
import { AppLevelAlertService } from '../alerts/app-level-alert.service';
import { HelpItem } from '../help-item';
import { HelpSearchService } from '../help-search.service';
@Component({
selector: 'app-help-search',
templateUrl: './help-search.component.html',
styleUrls: ['./help-search.component.scss'],
providers: [HelpSearchService]
})
export class HelpSearchComponent implements OnInit {
@ViewChild('overlay') overlay: ElementRef;
searching: Subject<boolean> = new Subject<boolean>();
helpItems: Observable<HelpItem[]>;
private searchTerms = new Subject<string>();
constructor(
private alertService: AppLevelAlertService,
private helpSearchService: HelpSearchService) {
this.searching.subscribe(searching => this.overlay.nativeElement.style.display = searching ? 'block' : 'none');
}
/**
* Push a search term into the observable stream.
*/
search(term: string): void {
this.searching.next(true);
this.searchTerms.next(term);
}
ngOnInit() {
this.helpItems = this.searchTerms
.debounceTime(300)
.distinctUntilChanged()
.switchMap(term => {
const results = term
? this.helpSearchService.search(term)
: Observable.of<HelpItem[]>([]);
return results;
})
.catch(error => {
this.alertService.errorOccurred.emit(new Error(error._body.error));
return Observable.of<HelpItem[]>([]);
});
this.helpItems.subscribe(thing => this.searching.next(false));
}
}
<div id="search-component">
<div class="form-group">
<label for="search-box">Search: </label>
<input type="text" #searchBox id="search-box" (keyup)="search(searchBox.value)" />
</div>
<div #overlay id="overlay">
<span class="spinner spinner-lg">
Loading...
</span>
</div>
<app-help-item *ngFor="let helpItem of helpItems | async" [helpItem]="helpItem"></app-help-item>
</div>