Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nesting repeaters for BelongsToMany relationships #13069

Open
marc31 opened this issue Jun 3, 2024 · 2 comments
Open

Nesting repeaters for BelongsToMany relationships #13069

marc31 opened this issue Jun 3, 2024 · 2 comments
Labels
bug Something isn't working low priority unconfirmed
Milestone

Comments

@marc31
Copy link

marc31 commented Jun 3, 2024

Package

filament/filament

Package Version

v3.2

Laravel Version

v11.9

Livewire Version

v3.5

PHP Version

PHP 8.3

Problem description

Following the example of using a repeater to fill BelongsToMany relationships [https://filamentphp.com/docs/3.x/forms/fields/repeater], I want to nest two repeaters with BelongsToMany relationships to handle a scenario like this:

I have Orders that have Products, which in turn have Colors.

I'm encountering a bug during the initial save: the color is not saved correctly because the order_product_id column in the color_order_product table is null. However, if I add new colors to a product in the order afterward, the modification is saved correctly.

But if I add a new product, the same issue arises.

Repeater::make('order_product')
    ->relationship('orderProducts')
    ->schema([
        Select::make('product_id')
            ->relationship('product', 'title')
            ->required()
            ->live(),
        Repeater::make('colorOrderProducts')
            ->relationship('colorOrderProducts')
            ->schema([
                Select::make('color_id')
                    ->options(
                        function ($get) {
                            $selectedProduct = Product::find($get('../../product_id'));
                            if ($selectedProduct) {
                                return $selectedProduct->colors()->get()->pluck('title', 'id');
                            }
                        }
                    )
                    ->required(),
            ])
    ])

Expected behavior

When creating an order, adding products, and assigning colors to those products using the nested repeater, all entries should be saved correctly.

Steps to reproduce

  1. Create an order with products and assign colors to those products using the nested repeater.

  2. Save the order.

  3. Check the color_order_product table and observe that the order_product_id column is null for the initially added colors.

  4. Add new colors to the existing product and save again. Observe that these new colors are saved correctly.

  5. Add a new product to the order and assign colors. Save and observe the issue reoccurs.

Reproduction repository

https://github.com/marc31/filament-nested-repeater-w-relationship

Relevant log output

No response

Donate 💰 to fund this issue

  • You can donate funding to this issue. We receive the money once the issue is completed & confirmed by you.
  • 100% of the funding will be distributed between the Filament core team to run all aspects of the project.
  • Thank you in advance for helping us make maintenance sustainable!
Fund with Polar
@marc31 marc31 added bug Something isn't working medium priority unconfirmed labels Jun 3, 2024
@polar-sh polar-sh bot added the Fund label Jun 3, 2024
@danharrin danharrin removed the fund label Jun 4, 2024
@Khant-Nyar
Copy link

Khant-Nyar commented Jun 5, 2024

that was the same for me if you have a solution for this ,pldas

My Resource

<?php

namespace App\Filament\Resources;

use App\Filament\Enums\AdvantageLayoutTypeEnum;
use App\Filament\Resources\ProductCategoryResource\Pages;
use App\Models\ProductCategory;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Concerns\Translatable;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Support\Str;

class ProductCategoryResource extends Resource
{
    use Translatable;

    protected static ?string $model = ProductCategory::class;

    protected static ?string $navigationIcon = 'heroicon-o-queue-list';

    protected static ?string $navigationGroup = 'Manage Products';

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\Components\TextInput::make('name')
                    ->required()
                    ->maxLength(255)
                    ->live(onBlur: true)
                    ->afterStateUpdated(function (string $operation, $state, Forms\Set $set): void {
                        if ($operation !== 'create') {
                            return;
                        }

                        $set('slug', Str::slug($state));
                    }),

                Forms\Components\TextInput::make('slug')
                    ->disabled()
                    ->dehydrated()
                    ->required()
                    ->maxLength(255)
                    ->unique(ProductCategory::class, 'slug', ignoreRecord: true),
                Forms\Components\FileUpload::make('icon')
                    ->image(),
                Forms\Components\FileUpload::make('image')
                    ->image(),
                Forms\Components\Repeater::make('advantages')
                    ->schema([
                        Forms\Components\TextInput::make('title')
                            ->required(),
                        Forms\Components\Repeater::make('contents')
                            ->schema([
                                Forms\Components\TextInput::make('order')
                                    ->numeric()
                                    ->required(),
                                Forms\Components\TextInput::make('title')
                                    ->required(),
                                Forms\Components\FileUpload::make('img')
                                    ->disk('public')
                                    ->directory('advantages')
                                    ->image(),
                                Forms\Components\MarkdownEditor::make('desc')
                                    ->required(),
                                Forms\Components\Select::make('type')
                                    ->options(AdvantageLayoutTypeEnum::class)
                                    ->required(),
                            ])
                            ->minItems(1)
                            ->collapsible()
                            ->required(),
                    ])
                    ->minItems(1)
                    ->addable(false)
                    ->deletable(false)
                    ->required()
                    ->columnSpanFull(),

            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('name')
                    ->searchable(),
                Tables\Columns\TextColumn::make('slug')
                    ->searchable()
                    ->toggleable(isToggledHiddenByDefault: true),
                Tables\Columns\ImageColumn::make('icon'),
                Tables\Columns\ImageColumn::make('image'),
                // Tables\Columns\TextColumn::make('advantages.title')
                //     ->searchable(),
                Tables\Columns\TextColumn::make('created_at')
                    ->dateTime()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                Tables\Columns\TextColumn::make('updated_at')
                    ->dateTime()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                //
            ])
            ->actions([
                Tables\Actions\EditAction::make(),
            ])
            ->bulkActions([
                Tables\Actions\BulkActionGroup::make([
                    Tables\Actions\DeleteBulkAction::make(),
                ]),
            ]);
    }

    public static function getRelations(): array
    {
        return [
            //
        ];
    }

    public static function getPages(): array
    {
        return [
            'index'  => Pages\ListProductCategories::route('/'),
            'create' => Pages\CreateProductCategory::route('/create'),
            'edit'   => Pages\EditProductCategory::route('/{record}/edit'),
        ];
    }
}

my migration


Schema::create('product_categories', function (Blueprint $table): void {
            $table->id();
            $table->text('name');
            $table->string('slug')->unique();
            $table->string('icon')->nullable()->default(null);
            $table->string('image')->nullable()->default(null);
            $table->json('advantages')->nullable();
            $table->timestamps();
        });


my seeder

$category = ProductCategory::create([
                    'name'       => $categoriesName,
                    'slug'       => Str::slug($categoriesName),
                    'icon'       => 'advantages/01HZE5794C7ADXYKC9HPXHFHS2.png',
                    'image'      => 'advantages/01HZE5794A1KQQYGAQQ9V7Y8B6.png',
                    'advantages' => [
                        [
                            'title'    => 'Advantages of Bio Stimulant',
                            'contents' => [
                                [
                                    'order' => 1,
                                    'title' => 'BioStimulants Assits In Combating The Effects Of Enveromental Stresses',
                                    'img'   => 'advantages/01HZE5794A1KQQYGAQQ9V7Y8B6.png',
                                    'desc'  => fake()->paragraph(),
                                    'type'  => 'right section',
                                ], [
                                    'order' => 2,
                                    'title' => 'Qui aute corporis no',
                                    'img'   => 'advantages/01HZE5794C7ADXYKC9HPXHFHS2.png',
                                    'desc'  => fake()->paragraph(),
                                    'type'  => 'left section',
                                ],
                                [
                                    'order' => 3,
                                    'title' => 'Advantage 1',
                                    'img'   => 'advantage1.png',
                                    'desc'  => fake()->paragraph(),
                                    'type'  => 'right section',
                                ],
                                [
                                    'order' => 4,
                                    'title' => 'Advantage 2',
                                    'img'   => 'advantage2.png',
                                    'desc'  => fake()->paragraph(),
                                    'type'  => 'final section',
                                ],
                            ],
                        ],
                    ],
                ]);

@zepfietje zepfietje added this to the v3 milestone Jun 8, 2024
@balu-lt
Copy link

balu-lt commented Jun 26, 2024

Not sure if I’m having the same issue, but here:

app/Models/Guide.php

public function items(): BelongsToMany
{
    return $this->belongsToMany(Item::class);
}
Forms\Components\Repeater::make('steps')
    ->schema([
        Forms\Components\Select::make('item')
            ->relationship(name: 'items', titleAttribute: 'title')
            ->disableOptionsWhenSelectedInSiblingRepeaterItems()
            ->required(),
        Forms\Components\Textarea::make('description')
            ->autosize(),
    ]),

Desired behaviour:
To sync all repeater step items into the guide_item table.

Current behaviour:
It removes all current relations and attaches only the last repeater step item.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working low priority unconfirmed
Projects
Status: Todo
Development

No branches or pull requests

5 participants