angular - Bootstrap typeahead 不传递'term'值并得到“找不到'object'类型的不同支持对象'[object Object]'
问题描述
我有一个带有 Bootstrap 4.2.1 的 Angular 7.2.4 应用程序。我想调用一个后端服务来填充一个自动完成输入框,但我遇到了麻烦,即使我已经有一个简单的引导输入。
html页面:
<div class="form-group" [class.has-danger]="searchFailed">
<label class="form-control-label" jhiTranslate="gatewayApp.legalAddress.fullAddress" for="field_fullAddress">Full Address</label>
<ng-template #rt let-r="result" let-t="term">
<ngb-highlight [result]="r.fullAddress" [term]="t"></ngb-highlight>
</ng-template>
<input type="text" class="form-control" name="fullAddress" id="field_fullAddress"
[(ngModel)]="legalAddress.fullAddress" [ngbTypeahead]="searchAddress" placeholder="n°, nome via, città"
[resultTemplate]="rt"
[resultFormatter]="formatter"
[inputFormatter]="formatter" />
<span *ngIf="searching">searching...</span>
<div class="form-control-feedback" *ngIf="searchFailed">Sorry, suggestions could not be loaded.</div>
</div>
服务:
type EntityArrayResponseType = HttpResponse<IAddress[]>;
query(req?: any): Observable<EntityArrayResponseType> {
console.log('[address.service.ts] query');
const param = new HttpParams().set('searchCriteria', ADDRESS_OTHER_TYPE_CODE);
return this.http.get<IAddress[]>(`${this.resourceUrl}/findbycriteria`, { params: param, observe: 'response' });
}
该模型:
export interface IAddress {
id?: number;
addressType?: string;
...
fullAddress?: string;
}
export class Address implements IAddress {
constructor(
public id?: number,
public addressType?: string,
...
public fullAddress?: string
) {}
}
控制器:
searchAddress = (text$: Observable < string >) =>
text$.pipe(
debounceTime(300),
distinctUntilChanged(),
tap(() => (this.searching = true)),
switchMap(term =>
this.geoLocalizationService.query(term).pipe(
tap(() => (this.searchFailed = false)),
catchError(() => {
this.searchFailed = true;
return of([]);
})
)
),
tap(() => (this.searching = false))
)
formatter = (x: {fullAddress: string}) => x.fullAddress;
两个问题:
1)填充fullAddress
输入框确实会触发searchAddress
但geoLocalizationService.query
总是收到一个空term
并将null发送到底层后端服务
2) 强制后端服务返回结果作为测试,不会使输入框中不显示任何数据。得到这个:
[geo-localization.service.ts] query geo-localization.service.ts:18:8
ERROR Error: "Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays."
Angular 6
View_NgbTypeaheadWindow_0 NgbTypeaheadWindow.html:5
Angular 8
node_modules ng-bootstrap.js:11024
RxJS 41
Angular 8
NgbTypeaheadWindow.html:5:4
View_NgbTypeaheadWindow_0 NgbTypeaheadWindow.html:5
Angular 5
RxJS 5
Angular 11
ERROR CONTEXT
Object { view: {…}, nodeIndex: 4, nodeDef: {…}, elDef: {…}, elView: {…} }
NgbTypeaheadWindow.html:5:4
View_NgbTypeaheadWindow_0 NgbTypeaheadWindow.html:5
Angular 5
RxJS 5
Angular 11
提前致谢!
==========
由于一个愚蠢的参数,解决了第 1 点。现在,当我收到以下消息时,我可以正确访问后端服务:
[[{"place_id":48841472,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"node","osm_id":3749006665,"boundingbox":["46...","46...","13...","13...."],"lat":"46....","lon":"13....","display_name":"---","class":"place","type":"house","importance":0.411,"address":{"house_number":"5","road":"---a","neighbourhood":"---","suburb":"---","city":"---","county":"---","state":"---","postcode":"---","country":"---","country_code":"---"}}]]
现在仍然有第 2 点错误,我认为是因为该服务有问题:
@Injectable({ providedIn: 'root' })
export class GeoLocalizationService {
public resourceUrl = SERVER_API_URL + 'api/geolocalization/addresses';
constructor(protected http: HttpClient) {}
query(req?: any): Observable<EntityArrayResponseType> {
console.log('[geo-localization.service.ts] query' + req);
const param = new HttpParams().set('searchString', req);
return this.http.get<IAddress[]>(this.resourceUrl, {
params: param, observe: 'response' });
}
}
可能这不是返回 Observable 的正确方法。我应该使用订阅来返回它吗?在另一个类中,这是有效的:
provinces: IDomainBean [];
ngOnInit() {
this.legalPersonService.findAllProvinces().subscribe(
(res: HttpResponse<IDomainBean[]>) => {
this.provinces = res.body;
},
(res: HttpErrorResponse) => this.onLegalFormTypeError(res.message)
);
}
searchProvince = (text$: Observable< string >) =>
text$.pipe(
debounceTime(200),
distinctUntilChanged(),
map(term => term === '' ? []
: this.provinces.filter(v => v.description.toLowerCase().indexOf(term.toLowerCase()) > -1).slice(0, 10))
)
formatter = (x: {description: string}) => x.description;
解决方案
几乎解决了......现在我可以通过以下更改查询服务:
1)ngModel中的“address”而不是“address.fullAddress”:
<input type="text" class="form-control" name="fullAddress" id="field_fullAddress"
[(ngModel)]="address" [ngbTypeahead]="searchAddress" placeholder="n°, nome via, città"
[resultTemplate]="rt"
[resultFormatter]="formatter"
[inputFormatter]="formatter" />
2)改变服务:
searchAddress = (text$: Observable <string>) =>
text$.pipe(
debounceTime(300),
distinctUntilChanged(),
tap(() => (this.searching = true)),
switchMap(term =>
this.geoService(term).pipe(
tap(() => (this.searchFailed = false)),
catchError(() => {
this.searchFailed = true;
return of([]);
})
)
),
tap(() => (this.searching = false))
)
formatter = (x: {fullAddress: string}) => x.fullAddress;
geoService(term: String): Observable <IGeoAddress []> {
if (term === '') {
return of([]);
}
return this.geoLocalizationService.queryGeoAddress(term).pipe(
map(res => {
return res.body.map(add => {
const addnew = new Address(
// setting initial address values
this.address.idSubject,
this.address.idContact,
add.latitude,
add.longitude,
...
);
return addnew;
});
})
);
}
如果它可以帮助其他人或者可以改进。
推荐阅读
- angular - 在 Angular 中使用 ngx-translate 翻译 datatable.net
- css - 如何在移动视图中居中徽标?
- gnuplot - Gnuplot:如何(系统地)将每列乘以一个因子
- python - GridSearchCV & RandomizedSearchCV - 你在运行后重新调整模型吗
- matlab - 在Matlab中构建递归函数以绘制自适应梯形求积
- python - 从命令行的输出逐行处理
- python - 如何从数据集中按“区域”访问?
- javascript - jquery.marquee.js 不能与 angularjs 一起运行
- python - 重新加载页面后如何始终在 Django 模板中显示模型数据?
- google-apps-script - Google Apps 脚本 - webapp 中使用的类方法的回调