JHipster: реализовать автозаполнение, заменив ComboBox на NgbTypeahead с наблюдаемым - PullRequest
1 голос
/ 21 апреля 2020

Я хочу заменить комбинированный список, используемый в JHipster (6.8.0), на поле «Автозаполнение». В блоге Антонио Гонсалвеса я нашел способ сделать это с PrimeNG , но я не хотел добавлять еще одну новую библиотеку виджетов.

Я понял, что JHipster уже использует библиотеку "Bootstrap widgets" (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 {
    Contact{language(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 , но этот метод использует RX JS и возвращает« Observable », и я не знаю, как ждать окончания http-запроса для прохождения результат для функции .

метод начального запроса, сгенерированный

  query(req?: any): Observable<EntityArrayResponseType> {
    const options = createRequestOption(req);
    return this.http.get<ILanguage[]>(this.resourceUrl, { params: options, observe: 'response' });
  }

Если кто-нибудь может помочь мне с этим?

1 Ответ

0 голосов
/ 24 апреля 2020

Наконец, я нашел способ повторно использовать сгенерированный 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 () метод not нужно больше.

...