skip to Main Content

Hello i am facing an issue in filament v3.I am making an order form using repeater in which there is relation with product table. The thing i want to do is by selecting product in select the other fields that i created outside the repeater should update accordingly.So I am using afterStateUpdated on repeater. I changes the fields inside the repeater but the fields in the other section outside the repeater are not updating. heres the code:

Repeater::make('products')
                    ->relationship()

                    ->schema([
                        Select::make('product_id')
                            ->label("Products")
                            ->relationship('product','name')
                            ->options(
                                $products->mapWithKeys(function (Product $product) {
                                    return [$product->id => sprintf('%s ($%s)', $product->name, $product->price)];
                                })
                            )
                            ->disableOptionWhen(function ($value, $state, Get $get) {
                                return collect($get('../*.product_id'))
                                    ->reject(fn($id) => $id == $state)
                                    ->filter()
                                    ->contains($value);
                            })
                            ->required()

                            ->createOptionForm([
                                FormsComponentsFileUpload::make('image')
                                    ->image()
                                    ->required(),
                                FormsComponentsTextInput::make('name')
                                    ->required()
                                    ->maxLength(255),
                                FormsComponentsRichEditor::make('description')
                                    ->required()
                                    ->maxLength(65535)
                                    ->columnSpanFull(),
                                FormsComponentsTextInput::make('sku')
                                    ->label('SKU')
                                    ->required()
                                    ->maxLength(255),
                                FormsComponentsTextInput::make('price')
                                    ->required()
                                    ->maxLength(255)
                                    ->numeric(),
                                FormsComponentsTextInput::make('qty')
                                    ->required()
                                    ->maxLength(255)
                                    ->numeric(),
                                FormsComponentsSelect::make('availablity')
                                    ->options([
                                        "yes" => "Yes",
                                        'no' => "No"
                                    ])
                                    ->required(),
                                FormsComponentsSelect::make('brands')
                                    ->relationship('brands', 'name')
                                    ->required()
                                    ->multiple()
                                    ->preload()
                                    ->createOptionForm([
                                        FormsComponentsTextInput::make('name')
                                            ->required()
                                            ->maxLength(255),
                                        FormsComponentsToggle::make('active')
                                            ->required(),
                                    ]),
                                FormsComponentsSelect::make('categories')
                                    ->relationship('categories', 'name')
                                    ->required()
                                    ->multiple()
                                    ->preload()
                                    ->createOptionForm([
                                        FormsComponentsTextInput::make('name')
                                            ->required()
                                            ->maxLength(255),
                                        FormsComponentsTextInput::make('description')
                                            ->required()
                                            ->maxLength(255),
                                        FormsComponentsToggle::make('active')
                                            ->required(),
                                    ]),
                                FormsComponentsSelect::make('warehouse_id')
                                    ->relationship('warehouse', 'name')
                                    ->required()
                                    ->createOptionForm([
                                        FormsComponentsTextInput::make('name')
                                            ->required()
                                            ->maxLength(255),
                                        Toggle::make('active')
                                    ])
                            ])
                            // ->reactive()
                            // ->afterStateUpdated(function ($state, callable $set) {
                            //     $product = Product::find($state);
                            //     if ($product) {

                            //         $set('product_id', $state);
                            //         $set('price', $product->price);
                            //     }
                            // })

                            ->columnSpan([
                                "md" => 5
                            ]),
                        TextInput::make('amount')
                            ->numeric()
                            ->required()
                            ->reactive()
                            ->label('Quantity')
                            // ->afterStateUpdated(function ($state, callable $set, Get $get) {
                            //     $product = Product::find($get('product_id'));
                            //     if(isset($product->price)){
                            //         $set('price', $product->price *$state);
                            //     }

                            // })

                            ->default(1)
                            ->columnSpan([
                                "md" => 3
                            ]),
                        TextInput::make('price')
                            ->disabled()
                            ->numeric()
                            ->minValue('1')
                            ->required()
                            ->default(1)
                            ->dehydrated()
                            ->columnSpan([
                                "md" => 2
                            ]),

                    ])->columns(["md" => 10])
                    ->live()
                    // After adding a new row, we need to update the totals
                    ->afterStateUpdated(fn ($state) => dd($state))
                    // After deleting a row, we need to update the totals
                    ->deleteAction(
                        fn(Action $action) => $action->after(fn(Get $get, Set $set) => self::updateTotals($get, $set)),
                    )
                    // Disable reordering
                    ->reorderable(false)
            ])->collapsible(),

the other section code is here:

Section::make()
            ->columns(1)
            ->maxWidth('1/2')->schema([
                TextInput::make('subtotal')
                ->numeric()
                ->readOnly()
                ->afterStateHydrated(function (Get $get, Set $set) {
                    self::updateTotals($get, $set);
                }),
                // TextInput::make('taxes')->required()->numeric()->default()
                TextInput::make('total')->readOnly()->numeric()
            ])

and the function updateTotals is here:

public static function updateTotals(Get $get, Set $set): void

{
// Retrieve all selected products and remove empty rows
$selectedProducts = collect($get(‘products’))->filter(fn($item) => !empty($item[‘product_id’]) && !empty($item[‘amount’]));

// Retrieve prices for all selected products
$prices = Product::find($selectedProducts->pluck('product_id'))->pluck('price', 'id');

// Calculate subtotal based on the selected products and quantities
$subtotal = $selectedProducts->reduce(function ($subtotal, $product) use ($prices) {
    return $subtotal + ($prices[$product['product_id']] * $product['amount']);
}, 0);

// Update the state with the new values
$set('subtotal', number_format($subtotal, 2, '.', ''));
$set('total', number_format($subtotal + ($subtotal * ($get('taxes') / 100)), 2, '.', ''));

}

i have taken this code from laravel Daily heres the link:code picked from here

2

Answers


  1. Chosen as BEST ANSWER

    Instead of using stateUpdate On repeater i have used placeholder and inside placeholder i am getting repeater fields and achieving the required results as follow

    return $form
            ->schema([
                Section::make('Customer Details')->schema([
                    FormsComponentsSelect::make('customer_id')
                        ->relationship('customer', 'name')
                        ->preload()
                        ->createOptionForm([
                            FormsComponentsTextInput::make('name')
                                ->required()
                                ->maxLength(255),
                            FormsComponentsTextInput::make('phone_no')
                                ->required()
                                ->maxLength(255),
                            FormsComponentsTextInput::make('email')
                                ->email()
                                ->required()
                                ->maxLength(255),
                        ])
                        ->required(),
                    FormsComponentsTextInput::make('invoice_no')
                        ->required()
                        ->maxLength(255),
                    FormsComponentsDateTimePicker::make('order_date')
                        ->required(),
                    FormsComponentsSelect::make('order_status')
                        ->options([
                            "received" => "Received",
                            "pending" => "Pending",
                            "ordered" => "Ordered"
    
                        ])
                        ->required(),
    
                    FileUpload::make('document'),
                    TextInput::make('total')->hidden()->disabled()
                    ->dehydrated()
                ])->collapsed()->columns(2),
    
                Section::make('Product Details')->schema([
                    Repeater::make('products')
                        ->relationship()
                        ->schema([
                            Select::make('product_id')
                                ->label("Products")
                                ->relationship('product','name')
                                ->live()
    
                                ->required()
    
                                ->createOptionForm([
                                    FormsComponentsFileUpload::make('image')
                                        ->image()
                                        ->required(),
                                    FormsComponentsTextInput::make('name')
                                        ->required()
                                        ->maxLength(255),
                                    FormsComponentsRichEditor::make('description')
                                        ->required()
                                        ->maxLength(65535)
                                        ->columnSpanFull(),
                                    FormsComponentsTextInput::make('sku')
                                        ->label('SKU')
                                        ->required()
                                        ->maxLength(255),
                                    FormsComponentsTextInput::make('price')
                                        ->required()
                                        ->maxLength(255)
                                        ->numeric(),
    
                                    FormsComponentsSelect::make('availablity')
                                        ->options([
                                            "yes" => "Yes",
                                            'no' => "No"
                                        ])
                                        ->required(),
                                    FormsComponentsSelect::make('brands')
                                        ->relationship('brands', 'name')
                                        ->required()
                                        ->multiple()
                                        ->preload()
                                        ->createOptionForm([
                                            FormsComponentsTextInput::make('name')
                                                ->required()
                                                ->maxLength(255),
                                            FormsComponentsToggle::make('active')
                                                ->required(),
                                        ]),
                                    FormsComponentsSelect::make('categories')
                                        ->relationship('categories', 'name')
                                        ->required()
                                        ->multiple()
                                        ->preload()
                                        ->createOptionForm([
                                            FormsComponentsTextInput::make('name')
                                                ->required()
                                                ->maxLength(255),
                                            FormsComponentsTextInput::make('description')
                                                ->required()
                                                ->maxLength(255),
                                            FormsComponentsToggle::make('active')
                                                ->required(),
                                        ]),
                                    FormsComponentsSelect::make('warehouse_id')
                                        ->relationship('warehouse', 'name')
                                        ->required()
                                        ->createOptionForm([
                                            FormsComponentsTextInput::make('name')
                                                ->required()
                                                ->maxLength(255),
                                            Toggle::make('active')
                                        ])
                                ])
                                ->reactive()
                                ->afterStateUpdated(function ($state, callable $set) {
                                    $product = Product::find($state);
                                    if ($product) {
    
                                        $set('product_id', $state);
                                        $set('price', $product->price);
                                    }
                                })
    
                                ->columnSpan([
                                    "md" => 5
                                ]),
                            TextInput::make('amount')
                                ->numeric()
                                ->required()
                                ->live(onBlur:true)
                                ->label('Quantity')
                                ->afterStateUpdated(function ($state, callable $set, Get $get) {
                                    $product = Product::find($get('product_id'));
                                    if(isset($product->price)){
                                        $set('price', $product->price *$state);
                                    }
    
                                })
    
                                ->default(1)
                                ->columnSpan([
                                    "md" => 3
                                ]),
                            TextInput::make('price')
                                ->disabled()
                                ->numeric()
                                ->required()
                                ->dehydrated()
                                ->columnSpan([
                                    "md" => 2
                                ]),
    
                        ])->columns(["md" => 10])
                        ->live()
                        ->defaultItems(0)
                ])->collapsible(),
    
                Section::make()->schema([
                    TextInput::make("amount")
                                ->label("Total Price")
                                ->disabled()
                                ->placeholder(function (Get $get , callable $set) {
                                    $fields = $get('products');
                                    $sum = 0;
                                    foreach($fields as $field){
                                        // foreach ($field as $value){
                                        //     if ($value == ""){
                                        //         $value = 0;
                                        //     }
                                        //     elseif(is_numeric($value)){
                                        //         $sum += $value;
                                        //     }
    
                                        // }
                                        $sum+=$field['price'];
                                    }
                                    $set('total',$sum);
                                    return $sum;
                                }),
                            //
    
                ]),
    
            ]);
    

  2. On your Repeater you have:

    ->afterStateUpdated(fn ($state) => dd($state))
    

    Is it the problem?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search