Angular 9中禁用NgbTypehead多实例同时展开问题求助
解决NgbTypehead多输入框下拉同时展开的问题
我来帮你搞定这个问题!你现在遇到的核心问题是所有输入框共用了同一个focus和click Observable,所以不管点击哪个输入框,所有的NgbTypehead都会接收到事件并展开下拉列表。要解决这个,我们需要给每个输入框分配独立的事件流。
解决方案步骤:
- 为每个输入项创建独立的Subject:给你的每个expense对象添加专属的
focus和clickSubject,这样每个输入框的事件只会触发自己的流。 - 调整搜索方法,绑定对应输入项的事件流:修改
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
相关产品推荐
相关产品推荐

