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

如何在Filament的Repeater组件中移除已选Select选项

实现Repeater中Select选项去重(排除已选Section)

要实现新增Repeater项时自动过滤已选的Section,核心是在section_id的Select组件中,动态获取当前Repeater所有已提交的Section ID并排除它们。以下是具体修改方案:

关键修改点

  • 通过Get助手获取整个Repeater的状态集合,提取已选的section_id
  • 查询Section时使用whereNotIn排除已选ID,同时保留当前编辑项的ID(避免编辑现有条目时自身被过滤)
  • 优化itemLabel的查询逻辑,提升性能

修改后的完整代码

Repeater::make('meal')
    ->relationship('meal')
    ->itemLabel(function (array $state): string{
        // 优化查询:直接find替代where+get,更高效
        return Section::find($state['section_id'])?->name ?? '';
    })
    ->schema([
        Hidden::make('order_id')->default(1),
        Select::make('section_id')
            ->label('Section')
            ->searchable()
            ->options(function (Get $get) {
                // 获取当前Repeater所有已有的项
                $repeaterItems = collect($get('../'));
                
                // 收集已选的Section ID,排除当前项的ID(编辑场景下保留自身)
                $existingSectionIds = $repeaterItems
                    ->filter(fn($item) => isset($item['section_id']))
                    ->pluck('section_id')
                    ->filter(fn($id) => $id !== $get('section_id'))
                    ->toArray();

                // 查询未被选中的Section
                return Section::query()
                    ->when(!empty($existingSectionIds), fn($query) => $query->whereNotIn('id', $existingSectionIds))
                    ->pluck('name', 'id')
                    ->toArray();
            })
            ->preload()
            ->required(),
        Select::make('product_id')
            ->label('Product')
            ->searchable()
            ->options(function (Get $get) {
                return Product::query()
                    ->where('section_id', $get('section_id'))
                    ->where('is_business', false)
                    ->where('status', true)
                    ->get()
                    ->pluck('name', 'id')
                    ->toArray();
            })
            ->preload()
            ->required(),
    ])
    ->columns()
    ->minItems(1)
    ->maxItems(Section::all()->count())
    ->cloneable()
    ->columnSpanFull()
    ->deleteAction(
        fn(Action $action) => $action->requiresConfirmation(),
    )
    ->addActionLabel('Add New Meal'),

逻辑说明

  1. 获取Repeater状态:$get('../')可以获取当前Repeater组件的所有项的状态集合,../表示向上遍历一层到Repeater本身
  2. 过滤已选ID:收集所有已存在的section_id,同时排除当前项的ID(如果是编辑已有条目,不会把自己从选项中移除)
  3. 动态查询选项:根据已选ID列表,用whereNotIn过滤Section查询结果,确保新增项只能选择未被选中的Section

内容的提问来源于stack exchange,提问作者Hardik Kanajariya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 22:35:26