Search code examples
laravelformslaravel-livewire

Laravel Filament: sum and count repeater


I'm making a form using filament. I want to count the number of repeater I make, and the sum of the value I input.

What I expected

I want to make the default value of Total area is the sum of Field area, and the default value of Number of fields is to count the Field I generate. After reading the documentation, I don't think there are such features. But, I just want to make sure if there is a trick to make this happen.

I tried to count($get('fields'), but it thrown an error:

count(): Argument #1 ($value) must be of type Countable|array, null given 

Here's my code:

public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Card::make([
                    Grid::make(2)
                        ->schema([
                            TextInput::make("total_area")
                                ->label("Total area")
                                ->postfix('m²')
                                ->disabled()
                                ->default(fn (Closure $get) => $get('field')),
                            TextInput::make("number_of_field")
                                ->label("Number of fields")
                                ->disabled()
                                ->default(fn (Closure $get) => count($get('fields'))),
                        ]),

                ])->columnSpan(1),

                Card::make([
                    Select::make("measurement_type")
                        ->label("Measurement type")
                        ->required(),

                    Repeater::make('fields')
                        ->label('Field')
                        ->schema([
                            TextInput::make("field")
                                ->label("Field area")
                                ->postfix('m²')
                                ->required(),
                        ])
                ])->columnSpan(1)
            ])->columns(2);
    }

Solution

  • According to Dan's answer with some modification of my own, I should have used placeholder instead of default.

    My working code:

    public static function form(Form $form): Form
        {
            return $form
                ->schema([
                       Card::make([
                          Grid::make(2)
                            ->schema([
                                TextInput::make("total_area")
                                    ->label("Total Area")
                                    ->postfix('m²')
                                    ->disabled()
                                    ->placeholder(function (Closure $get) { 
                                        $fields = $get('fields');
                                        $sum = 0;
                                        foreach($fields as $field){
                                            foreach ($field as $value){
                                                if ($value == ""){
                                                    $value = 0;
                                                }
                                                $sum += $value;
                                            }
                                        }
                                        return $sum;
                                    }),
                                TextInput::make("number_of_fields")
                                    ->label("Number of Fields")
                                    ->disabled()
                                    ->placeholder(fn (Closure $get) => count($get('fields'))),
                            ]),
    
                    ])->columnSpan(1),
    
                    Card::make([
                        Select::make("measurement_type")
                            ->label("Measurement Type")
                            ->options(MeasurementType::all()->pluck('name'))
                            ->required(),
    
                        Repeater::make('fields')
                            ->schema([
                                TextInput::make("field")
                                    ->label("Field Area")
                                    ->postfix('m²')
                                    ->numeric()
                                    ->reactive()
                                    ->required()
                            ])
                            ->reactive()
                    ])->columnSpan(1)
                ])->columns(2);
        }
    

    Result as expected:

    result