#How to trigger a custom action modal directly from a TextInputColumn updateStateUsing?

44 messages · Page 1 of 1 (latest)

tired oyster
#

I have a TextInputColumn on a table for my resources route_id attribute. When this is changed to a route_id that does not exist, I want to prompt the user with an action modal, where they can create a new route record, which would update the route_id column with the id of the newly created route.
I am trying to do this:

TextInputColumn::make('route_id')
  ->rules(['numeric', 'integer', 'min:1'])
  ->extraAttributes(['style' => 'min-width:60px'])
  ->updateStateUsing(function ($state, $record) {
    if ($state > 1 || $state !== null) {
        $route = Route::find($state);

        if (!$route) {
          // Trigger the createRoute action if the route does not exist
          return Action::make('createRoute')
            ->form([
              TextInput::make('name')->required()->maxLength(255),
              ColorPicker::make('color')->required(),
            ])
            ->action(function (array $data) use ($state) {
              $data['id'] = $state;
              Route::create($data);
            })
            ->modalHeading('Create Route')
            ->modalSubmitActionLabel('Create')
            ->modalWidth('lg')
            ->visible(fn () => true);
      }
      $groupOrderUpdater = app(UpdatesGroupOrders::class);
      $groupOrderUpdater->update($record, ['route_id' => $state]);
    }
    return $record->route_id;
  }),

But the action modal does not get triggered at all, what am I doing wrong?

dusky rampartBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

tepid valve
#

Im also struggling to get this working for a checkboxColumn. Were you able to figure it out @tired oyster ?

tired oyster
#

Not yet, no :/

tepid valve
#

I even added a log::info to the function and it looks like it doesn’t get hit at all.

flat violet
kind tide
#

You can’t ‘make’ the action on demand. It’s too late in the lifecycle. It has to be registered during component creation. Then you can dispatch a mountAction(), mountTableAction() or mountFormComponentAction() via livewire with the action name and arguments.

#

Will probably need a custom column that extends TextColumn to register the action during setUp()

tepid valve
#

From what I’ve been reading, it seems like ->updateStateUsing() should be the way to modify how the state is stored right?

kind tide
tepid valve
#

I see that. In the code sample above you can see @tired oyster is using updateStateUsing(). I’ve also been calling it action in all of my googling today till about an hour ago when I figured out the difference.

kind tide
#

Also, only form input columns have the concept of updating state

tepid valve
#

I’m currently trying to also get ->updateStateUsing() to work on a form input column (i’ve tried checkbox, and toggle)

kind tide
#

Normal columns are essentially readonly. Vs something like a textInputColumn which does interact with state.

tepid valve
#

This is my particular column. ->getStateUsing() works great, but can not get ->updateStateUsing() to work to save my life. CheckboxColumn should be one of the form input columns right?


/checkbox column to hold the task complete/uncomplete controls
                    Tables\Columns\CheckboxColumn::make('status')
                        ->label('Completed')
                        ->getStateUsing(fn ($record) => $record->status == 'completed')
                        ->updateStateUsing(function ($state, Task $record){
                            //dd($record);
                            if ( $state == 1) {
                                $record->staus = 'completed';
                                $record->save();
                            } else {
                                $record->status = 'active';
                                $record->save();
                            }
                            return $state;
                        })
                        ->sortable(),
kind tide
#

Also, where are you getting updateStateUsing() ?

tepid valve
kind tide
#

It should be afterStateUpdated()

#

Just feels like you are trying to augment the state out of order for the lifecycle

tepid valve
#

Because im struggling to figure out and find documentation that I can understand that explains how i would translate a checkbox being checked, to a column being updated with the value of “completed”.

From digging around im seeing examples of form input columns using updateStateUsing() to get this done. I started digging into the code to figure it out and CheckboxColumn.php uses Concerns\CanUpdateState so i thought I was on the right track.

kind tide
#

Keep in mind that form input columns are not the same thing as a form input.

tepid valve
kind tide
#

Column inputs are limited in what they can do compared to actual form input fields.

#

Ah, that’s v2. That’s where it’s coming from. Are you on filament v2?

tepid valve
#

No, im on v3.

kind tide
#

Ok, so that method isn’t the same on v3.

tepid valve
#

I thought that could be a risk of old info, but again, with the CheckboxColumn class using CanUpdateState i assumed that was correct.

So, should my code look more like this:


Tables\Columns\CheckboxColumn::make('status')
                        ->label('Completed')
                        ->getStateUsing(fn ($record) => $record->status == 'completed')
                        ->beforeStateUpdated(function ($record, $state) {
                            Log::info('state: '.$state);
                            if ( $state == 1) {
                                $record->status = 'completed';
                                $record->save();
                            } else {
                                $record->status = 'active';
                                $record->save();
                            }
                        })
                        ->sortable()
kind tide
#

Should probably be after state updated, but you still need to return the state.

#

So in the callback, do what you need to with the state, but return what the modified state should be for the column.

tepid valve
#

Ok, that worked.

#

I was confused by the documentation saying “ // Runs after the state is saved to the database.” as if it was already stored in the database.

kind tide
#

Well it is after, but the stored state can be different than the displayed state. If that makes sense.

tepid valve
#

I do get that, but I think im still struggling with the wording.

I have it working now so im happy. Thanks for your help and patience as i wrap my brain around it. 😄

flat violet
# tired oyster I have a TextInputColumn on a table for my resources `route_id` attribute. When ...

We cannot register an Action here, I guess. I created a header action as a workaround. Is it elegant? No, but it might work for your case.

ListPage

protected function getHeaderActions(): array
{
    return [
        Actions\Action::make('createRoute')
            ->form([
                TextInput::make('name')->required()->maxLength(255),
                ColorPicker::make('color')->required(),
            ])
            ->action(function (array $arguments, array $data) {
                $data['id'] = $arguments['id'];
                Route::create($data);
            })
            ->modalHeading('Create Route')
            ->modalSubmitActionLabel('Create')
            ->modalWidth('lg')
            ->extraAttributes(['class' => 'hidden'])
    ];
}
TextInputColumn::make('route_id')
->updateStateUsing(function (Page $livewire, $state, Model $record) {
    if ($state > 1 || $state !== null) {
        //...
        $livewire->mountAction('createRoute', ['id' => $state]);
    }
})
tired oyster
dusky rampartBOT
flat violet
tired oyster
#

We can't have it all 🙂

flat violet
final mesa
wanton cobalt
final mesa