You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 9中禁用NgbTypehead多实例同时展开问题求助

解决NgbTypehead多输入框下拉同时展开的问题

我来帮你搞定这个问题!你现在遇到的核心问题是所有输入框共用了同一个focus和click Observable,所以不管点击哪个输入框,所有的NgbTypehead都会接收到事件并展开下拉列表。要解决这个,我们需要给每个输入框分配独立的事件流。

解决方案步骤:

  • 为每个输入项创建独立的Subject:给你的每个expense对象添加专属的focus和click Subject,这样每个输入框的事件只会触发自己的流。
  • 调整搜索方法,绑定对应输入项的事件流:修改search方法,让它接收当前的expense对象,返回只关联该输入框事件的搜索Observable。
  • 更新模板,绑定当前项的事件:在*ngFor循环里,把focus和click事件绑定到当前expense的Subject上,同时传入当前expense到search方法中。

具体代码实现:

TypeScript部分:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Observable, Subject, merge } from 'rxjs';
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators';

@Component({
  selector: 'app-your-component',
  templateUrl: './your-component.component.html',
  styleUrls: ['./your-component.component.css']
})
export class YourComponent implements OnInit, OnDestroy {
  // 假设这是你的expense列表
  expenses: any[] = [/* 初始化你的expense数据 */];
  // 示例费用选项列表
  expenseList: string[] = ['Travel', 'Meal', 'Office Supplies', 'Equipment', 'Software License'];

  ngOnInit() {
    // 为每个expense初始化独立的focus和click Subjects
    this.expenses.forEach(expense => {
      expense.focus = new Subject<string>();
      expense.click = new Subject<string>();
    });
  }

  // 每个输入框使用独立的搜索流
  search(expense: any) {
    return (text: Observable<string>) => {
      const debouncedText$ = text.pipe(debounceTime(200), distinctUntilChanged());
      // 只使用当前输入框的focus和click事件流
      const inputFocus$ = expense.focus;
      const inputClick$ = expense.click;

      return merge(debouncedText$, inputFocus$, inputClick$).pipe(
        map(term => {
          if (!term) {
            return this.expenseList;
          }
          // 简化匹配逻辑,用includes更直观
          return this.expenseList.filter(item => 
            item.toLowerCase().includes(term.toLowerCase())
          );
        })
      );
    };
  }

  // 组件销毁时清理Subject,防止内存泄漏
  ngOnDestroy() {
    this.expenses.forEach(expense => {
      expense.focus.complete();
      expense.click.complete();
    });
  }
}

HTML模板部分:

<div *ngFor="let expense of expenses; let i = index" class="form-group col-md-7 col-sm-12">
  <input 
    id="typeahead-template-{{i}}" 
    name="{{i}}_name" 
    type="text" 
    class="form-control" 
    [(ngModel)]="expense.expense" 
    [ngbTypeahead]="search(expense)" 
    placeholder="Select Expense" 
    (focus)="expense.focus.next($any($event).target.value)" 
    (click)="expense.click.next($any($event).target.value)"
  />
</div>

为什么这样有效?

每个输入框现在都有自己专属的focus和click事件流,当你点击或聚焦某个输入框时,只有对应的NgbTypehead会接收到事件并展开下拉列表,其他输入框不会受到影响。另外,组件销毁时调用complete()清理Subject,也能避免潜在的内存泄漏问题。

内容的提问来源于stack exchange,提问作者Saneth Chandrasekara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 17:22:51