我想使用ngBootstrap for Angular 4 Typeahead进行自动完成。他们用于远程数据检索的示例是使用Jsonp而不是http。在这个例子中,我一直在努力寻找更多信息来替换Jsonp和http。我对Observables不太熟悉,所以我正在努力学习它们并更好地了解它们。
我见过这个example,但看起来非常简单而且(?)为了简单起见而遗漏了很多东西?
有人指向正确的方向,我正在尝试使用带有ngBootstrap Typeahead的http找到一些很好的例子。
修改
{
"took": 15,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"hits": {
"total": 9,
"max_score": 4.2456956,
"hits": [
{
"_index": "query-index",
"_type": "autocomplete",
"_id": "AVxqBE-3t2o4jx2g0ntb",
"_score": 4.2456956,
"_source": {
"suggestions": "bruce"
}
},
{
"_index": "query-index",
"_type": "autocomplete",
"_id": "AVxqBE-3t2o4jx2g0ntc",
"_score": 3.064434,
"_source": {
"suggestions": "bruce wayne"
}
},
{
"_index": "query-index",
"_type": "autocomplete",
"_id": "AVxqBE-3t2o4jx2g0ntd",
"_score": 3.064434,
"_source": {
"suggestions": "bruce willis"
}
},
编辑2
export class AutocompleteComponent {
model: any;
searching = false;
searchFailed = false;
constructor(private autocompleteService: Elasticsearch) {}
//formatMatches = (query: any) => query.hits.hits._source.suggestions || '';
//formatMatches = (query: any) => query.hits.hits || '';
formatMatches = (query: any) => <any>response.json().hits.hits || '';
search = (text$: Observable<string>) =>
//search = (text$: Observable<Suggestion[]>) =>
text$
.debounceTime(300)
.distinctUntilChanged()
//.switchMap(term =>
//Observable.fromPromise(this.autocompleteService.search(term)
.switchMap(term =>
this.autocompleteService.search(term)
.do( () => this.searchFailed = false)
.catch( () => {
this.searchFailed = true;
return Observable.of([]);
}))
.do( () => this.searching = false);
}
答案 0 :(得分:4)
我想我知道如何解释它。但是,我正在构建一个处理过滤器的模态。下面是我的httpService。 getCarriers ,它带有一个搜索字符串。
getCarriers(query: string): Observable<any> {
return this._http.get(this._ripcord + '/carriers?search_string=' + query, this.options)
.map((response: Response) => <any>response.json().data)
.do(data => console.log(data))
.catch(this.handleError);
}
在我的模态组件(filters.component.ts)文件中,知道我的服务返回一个对象数组,我不得不创建一个 formatter 方法来处理输入和结果对象结构。
我认为由于ngbdTypeahead接受一个Observable,我会将该术语发送到我的httpservice并允许它返回一个Observable而不是尝试订阅它。
// filters.component.ts
import { Component, OnInit } from '@angular/core';
import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import { HttpService } from '../../../shared/http.service';
import { Carrier } from '../../../definitions/carrier';
@Component({
selector: 'afn-ngbd-modal-content',
templateUrl: './modal/filters.modal.html',
styleUrls: ['./modal/filters.modal.css']
})
export class NgbdModalContentComponent {
filtersForm: FormGroup;
carriers: Carrier[];
constructor(public activeModal: NgbActiveModal, public httpService: HttpService, private fb: FormBuilder) {
this.createForm();
}
carrier_search = (text$: Observable<string>) =>
text$
.debounceTime(200)
.distinctUntilChanged()
.do((text) => console.log(text))
.switchMap(term =>
this.httpService.getCarriers(term)
)
;
formatter = (x: {attributes: {name: string}}) => x.attributes.name;
createForm() {
this.filtersForm = this.fb.group({
name: ['', Validators.required],
});
}
}
@Component({
selector: 'afn-filters',
templateUrl: './filters.component.html',
styleUrls: ['./filters.component.css']
})
export class FiltersComponent implements OnInit {
constructor(private modalService: NgbModal) { }
open() {
const modalRef = this.modalService.open(NgbdModalContentComponent);
}
ngOnInit() {
}
}
这是我的模态的HTML模板:
// filters.modal.html
<div class="modal-header">
<h4 class="modal-title">Hi there!</h4>
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<!--<p>Hello, {{name}}!</p>-->
<form [formGroup]="filtersForm" novalidate>
<div class="form-group">
<label class="center-block">Carrier:
<input type="text" class="form-control" formControlName="name" [ngbTypeahead]="carrier_search" [inputFormatter]="formatter" [resultFormatter]="formatter">
</label>
</div>
</form>
<p>Form value: {{ filtersForm.value | json }}</p>
<p>Form status: {{ filtersForm.status | json }}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="activeModal.close('Close click')">Close</button>
</div>
如果有任何具体问题,请告诉我。在我开始工作之前,我有点被黑了。
毋庸置疑,即使debounceTime很棒,我仍然不想在用户键入至少3个字符之前执行请求。如果我尝试将该逻辑放在switchMap中,我会收到错误。