簡體   English   中英

如何停止或禁用 ngbTypeahead 輸入字段在焦點上打開,直到它完成映射所有數據

[英]How to stop or disable ngbTypeahead input field from opening on focus until it finishes mapping all the data

單擊輸入字段時,我需要預先輸入以顯示前 5 個結果。 我已經使用 ngbTypeahead 文檔制定了解決方案。

app.component.html

<div class="form-group g-0 mb-3">
  <input id="typeahead-prevent-manual-entry" type="text" class="form-control"
  placeholder="Big dataset"
  formControlName="bigDataset"
  [ngbTypeahead]="search"
  [inputFormatter]="valueFormatter"
  [resultFormatter]="valueFormatter"
  [editable]="false"
  [focusFirst]="false"
  (focus)="stateFocus$.next($any($event).target.value)"
  (click)="stateClick$.next($any($event).target.value)"
  #instance="ngbTypeahead" />
</div>

app.component.ts

type BigDataset: {
  id: string,
  name: string
}

export class AppComponent implements OnInit {
  dataset: BigDataset[];

  @ViewChild('instance', {static: true}) instance: NgbTypeahead;
  focus$ = new Subject<string>();
  click$ = new Subject<string>();

  constructor(
    private formBuilder: FormBuilder,
  ) { }

  ngOnInit(): void {
    this.dataForm = this.formBuilder.group({
      bigDataset: ["", [Validators.required]],
    });
  }

  getBigDataset() {
    //Excluded for simplicity. This returns a set of objects (~3000)
    //of type BigDataset and assigns it to this.dataset.
  }

  valueFormatter = (value: any) => value.name;

  search: OperatorFunction<string, readonly BigDataset[]> = (text$: Observable<string>) => {
    const debouncedText$ = text$.pipe(debounceTime(100), distinctUntilChanged());
    const clicksWithClosedPopup$ = this.click$.pipe(filter(() => !this.instance.isPopupOpen()));
    const inputFocus$ = this.focus$;

    return merge(debouncedText$, inputFocus$, clicksWithClosedPopup$).pipe(map(term => (term === '' ? this.dataset
        : this.dataset.filter(data => data.name.toLowerCase().indexOf(term.toLowerCase()) > -1)).slice(0, 5))
    );
  };
}

現在這有效 但是,問題是如果我在頁面初始化后立即單擊輸入字段,我會收到此錯誤:

ERROR TypeError: Cannot read properties of undefined (reading 'slice')
    at org-address.component.ts:93:109
    at map.js:7:1
    at OperatorSubscriber._next (OperatorSubscriber.js:9:1)
    at OperatorSubscriber.next (Subscriber.js:31:1)
    at subscribe._OperatorSubscriber__WEBPACK_IMPORTED_MODULE_1__.OperatorSubscriber.innerComplete (mergeInternals.js:25:1)
    at OperatorSubscriber._next (OperatorSubscriber.js:9:1)
    at OperatorSubscriber.next (Subscriber.js:31:1)
    at Subject.js:31:1
    at errorContext (errorContext.js:19:1)
    at Subject.next (Subject.js:26:21)

據我所知,這是因為預輸入試圖在完成 map function 之前顯示數據。 問題是如果我決定增加數據集,map 所需的時間可能會增加,因此等待未知的時間直到完成該過程不是一個選項。 我想禁用該字段或使用其他解決方案,直到它完成映射過程。

我曾嘗試禁用表單字段並在映射過程之后使用 finalize() 啟用它,但我似乎犯了一個錯誤並且該字段保持禁用狀態。

search: OperatorFunction<string, readonly BigDataset[]> = (text$: Observable<string>) => {
    this.dataForm.get('bigDataset')?.disable();
    const debouncedText$ = text$.pipe(debounceTime(100), distinctUntilChanged());
    const clicksWithClosedPopup$ = this.click$.pipe(filter(() => !this.instance.isPopupOpen()));
    const inputFocus$ = this.focus$;

    return merge(debouncedText$, inputFocus$, clicksWithClosedPopup$).pipe(
      finalize(() => this.dataForm.get('bigDataset')?.enable()),
      map(term => (term === '' ? this.dataset
        : this.dataset.filter(data => data.name.toLowerCase().indexOf(term.toLowerCase()) > -1)).slice(0, 5))
    );
  };

對此的任何幫助將不勝感激。

我的一個朋友實際上給了我一個非常簡單的解決方法,就是在數據過濾之后(拼接過程之前)添加可選鏈接。 添加'? 在調用 slice 方法之前,如果它嘗試在過濾過程完成之前返回值,它就像一個魅力一樣工作並且停止給出錯誤。

search: OperatorFunction<string, readonly BigDataset[]> = (text$: Observable<string>) => {
    const debouncedText$ = text$.pipe(debounceTime(100), distinctUntilChanged());
    const clicksWithClosedPopup$ = this.click$.pipe(filter(() => !this.instance.isPopupOpen()));
    const inputFocus$ = this.focus$;

    return merge(debouncedText$, inputFocus$, clicksWithClosedPopup$).pipe(map(term => (term === '' ? this.dataset
        : this.dataset.filter(data => data.name.toLowerCase().indexOf(term.toLowerCase()) > -1))?.slice(0, 5))
    );
  };

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM