
本文介绍通过自定义选项渲染顺序,实现在 ng-select 下拉列表中将已选选项固定显示在顶部,未选项列于其后,避免重复且提升用户体验。
本文介绍通过自定义选项渲染顺序,实现在 ng-select 下拉列表中将已选选项固定显示在顶部,未选项列于其后,避免重复且提升用户体验。
在默认行为下,ng-select 的下拉选项始终按原始数据顺序展示,已选项目仅在输入框中高亮,不会在下拉面板中“前置”。若需增强可操作性(例如多选场景中快速取消或二次确认),将已选项置顶是一种常见且实用的交互优化方案。其实现核心在于绕过默认的 items 输入绑定,改用
✅ 实现原理
关键在于分离数据源:
- originalArr:完整的可选项数组(如 ['Apple', 'Banana', 'Cherry', 'Date']);
- selectedArr:当前已选值数组(如 ['Banana', 'Cherry'])。
我们先渲染所有已选项,再遍历原始数组,仅渲染未被选中的项,从而自然实现“已选在前、未选在后”的视觉分层。
? 完整示例代码
<ng-select
[multiple]="true"
[(ngModel)]="selectedArr"
bindLabel="name"
bindValue="id"
placeholder="请选择...">
<!-- 步骤1:优先渲染已选项 -->
<ng-option *ngFor="let item of selectedArr" [value]="item.id">
{{ item.name }}
</ng-option>
<!-- 步骤2:渲染剩余未选项(排除已选) -->
<ng-container *ngFor="let item of originalArr">
<ng-option
*ngIf="!selectedArr.some(s => s.id === item.id)"
[value]="item.id">
{{ item.name }}
</ng-option>
</ng-container>
</ng-select>⚠️ 注意事项:
- 若 selectedArr 存储的是对象(推荐),请确保 *ngIf 中的比较逻辑基于唯一标识(如 id),避免引用相等性误判;
- 若使用原始字符串/数字类型,可简化为 !selectedArr.includes(item);
- ng-select 的 [(ngModel)] 仍绑定 selectedArr,无需额外处理双向同步;
- 此方案兼容搜索过滤(searchable),但搜索时已选项仍会出现在顶部——如需搜索时隐藏已选项,需结合 filterBy 自定义逻辑。
? 总结
该方法不依赖第三方插件或内部 API,完全基于 Angular 模板语法与 ng-select 的灵活插槽机制,轻量、可控、易于维护。适用于多选、标签管理、权限配置等需要高频切换已选项的业务场景。建议配合 trackBy 提升长列表渲染性能,并在复杂对象场景中封装为可复用的 @Input() 组件以统一行为。










