JHipster:通过将 ComboBox 替换为 NgbTypeahead 和 observable 来实现 AutoComplete
Posted
技术标签:
【中文标题】JHipster:通过将 ComboBox 替换为 NgbTypeahead 和 observable 来实现 AutoComplete【英文标题】:JHipster : implement AutoComplete by replacing ComboBox with a NgbTypeahead with observable 【发布时间】:2020-08-03 13:56:08 【问题描述】:我想用“自动完成”字段替换 JHipster(6.8.0) 中使用的组合框,我在 Antonio Goncalves's 博客上找到了使用 PrimeNG 的方法,但我做到了不想添加另一个新的小部件库。
我意识到 JHipster 已经在使用“Bootstrap 小部件”库 (https://ng-bootstrap.github.io) 通过“ngb-datepicker”输入日期。
此库提供了一个组件,允许使用 “Ngb-typeahead” 指令实现“自动完成”功能。 我不是 Angular 专家,所以我很难找到最好的方法。也就是说,要进行的更改相对较小,但最重要的是:可行。
有变化:
JDL 文件用于生成 JHipster 示例应用程序
entity Contact
firstName String required,
lastName String required,
email String
entity Language
alpha3b String required maxlength(3),
alpha2 String required maxlength(2)
name String required,
flag32 String,
flag128 String,
activated Boolean
relationship ManyToOne
Contactlanguage(name) required to Language
filter *
service all with serviceClass
paginate Contact with pagination
dto * with mapstruct
contact-update.component.html
将现有控件替换为:
<div class="form-group">
<label class="form-control-label" jhiTranslate="jhcontact2App.contact.language" for="field_language">Language</label>
<!-- <select class="form-control" id="field_language" name="language" formControlName="languageId"> -->
<!-- <option *ngIf="!editForm.get('languageId')!.value" [ngValue]="null" selected></option> -->
<!-- <option [ngValue]="languageOption.id" *ngFor="let languageOption of languages; trackBy: trackById"> languageOption.name </option> -->
<!-- </select> -->
<input type="text" class="form-control" id="field_language" formControlName="language"
placeholder=" 'jhcontact2App.contact.language.placeholder' | translate "
(selectItem)="selectedItem($event)"
[ngbTypeahead]="search"
[inputFormatter]="formatter"
[resultFormatter]="formatter"
[editable]='false' />
</div>
<div *ngIf="editForm.get('language')!.invalid && (editForm.get('language')!.dirty || editForm.get('language')!.touched)">
<small class="form-text text-danger"
*ngIf="editForm.get('language')?.errors?.required" jhiTranslate="entity.validation.required">
This field is required.
</small>
</div>
contact-update.component.ts
更新 ngOnInit、updateFrom、createForm 方法
ngOnInit(): void
this.activatedRoute.data.subscribe(( contact ) =>
this.updateForm(contact);
// remove service call to populate Languages Collection
// this.languageService.query()
// .subscribe((res: HttpResponse<ILanguage[]>) => (this.languages = res.body || []));
);
updateForm(contact: IContact): void
this.editForm.patchValue(
id: contact.id,
firstName: contact.firstName,
lastName: contact.lastName,
email: contact.email,
// Patch full Language object instead id
// languageId: contact.languageId,
language: id: contact.languageId, name: contact.languageName
);
private createFromForm(): IContact
// get full object from form
const language: ILanguage = this.editForm.get(['language'])!.value;
return
...new Contact(),
id: this.editForm.get(['id'])!.value,
firstName: this.editForm.get(['firstName'])!.value,
lastName: this.editForm.get(['lastName'])!.value,
email: this.editForm.get(['email'])!.value,
// languageId: this.editForm.get(['languageId'])!.value
languageId: language.id
;
添加 Ngb-typeahead 使用的新函数:
// Add formatter
formatter = (x: name: string ) => x.name;
// the seach function
search = (text$: Observable<string>) =>
text$.pipe(
debounceTime(300),
distinctUntilChanged(),
switchMap(term => this.languageService.searchByName( term ))
)
// the OnSelect
selectedItem(language: ILanguage): void
this.editForm.patchValue(
language: language.name
);
language.service.ts
searchByName(term: string): any
if (term === '')
return of([]);
const options = createRequestOption( 'name.contains': term );
return this.http.get<ILanguage[]>(this.resourceUrl, params: options );
最后一点并不完全让我满意,因为我想重用 language.service.ts 组件的“初始查询生成方法”,但是这个方法使用 RXJS 并返回一个“Observable "和我不知道如何等待http请求结束将结果传递给函数。
初始查询生成方法
query(req?: any): Observable<EntityArrayResponseType>
const options = createRequestOption(req);
return this.http.get<ILanguage[]>(this.resourceUrl, params: options, observe: 'response' );
如果有人可以帮我解决这个问题?
【问题讨论】:
http.get() 返回一个 Observable,您将 searchByName() 键入为“any”这一事实并没有改变这一点(阅读angular.io/guide/http)。我看不出 searchByName() 和 query() 之间没有真正的区别,在这两种情况下都会返回一个 Observable,您必须在其上调用 subscribe() 来处理服务器返回的数据。 感谢盖尔的关注,我的分析错了。 在 searchByName() 的情况下,该方法返回一个 ILanguage 的 observable,但在 Query() 的情况下,该方法返回一个我不能用作迭代的 HttpResponse 的 Observable。 【参考方案1】:终于,我找到了一种重用JHispter生成的“query()”方法的方法!
像这样:
// the search function
search = (text$: Observable<string>) =>
text$.pipe(
debounceTime(300),
distinctUntilChanged(),
switchMap(term => term.length < 2 ? [] : this.languageService.query( 'name.contains': term )),
map((res: HttpResponse<ILanguage[]>) => (res.body || []))
);
searchByName() 方法不再需要了。
【讨论】:
以上是关于JHipster:通过将 ComboBox 替换为 NgbTypeahead 和 observable 来实现 AutoComplete的主要内容,如果未能解决你的问题,请参考以下文章
无法在JHipster on Production上加载另一个页面