Update only one field in a custom action?

Hi guys, I would like to implement this: - if the user clicked the edit button, the edit form open - the form has multiple form components and a key-value component (this value stored in another table with HasOne relation) - the user made some changes then submit the edit form - after submit only one field (is_active) has been updated in the edited record, then a new record created with the posted data I try this:
protected function handleRecordUpdate(Model $record, array $data): Model
{
$record->update(['is_active' => 0]);
return static::getModel()::create($data);
}
protected function handleRecordUpdate(Model $record, array $data): Model
{
$record->update(['is_active' => 0]);
return static::getModel()::create($data);
}
Problem: All fields of original record has been updated (the related record has been updated too). How can i solve this? Thanks a lot!
27 Replies
wyChoong
wyChoong17mo ago
why you need to do this?
peterkeri
peterkeriOP17mo ago
because I have to keep the original record (for business reasons)
wyChoong
wyChoong17mo ago
will it be easier if you don't use the edit view, just add a "Disable" action button in the view page, and do your handling there not really sure why you need to duplicate the record and set disable to the old record, but probably is easier to just use an action button it kind of create a confusion where you set it to inactive, but a new record with active is created
peterkeri
peterkeriOP17mo ago
so i have to create a custom action what is replicating the original record and then inactive it?
wyChoong
wyChoong17mo ago
is this for audit history?
peterkeri
peterkeriOP17mo ago
not exactly, but almost.. the record (what I have to inactive) will be used by orders what created at the past the record what is active used by for select fields (these are the actual entries)
wyChoong
wyChoong17mo ago
so for the same order, you will have multiple inactive records but 1 active records?
peterkeri
peterkeriOP17mo ago
wait, i'll explain.. just a sec I have shipment orders what has different properties (for example package types). This package types contains important values (what we used for accountant modules). When a shipment record created it used the currently active package type entry. I should NOT modify these data, so thats why I have to create a new version of the package type recod every time when any data has changed. So all shipment orders used "his version" of the package tpye. i hope i can explain it clearly The package type records with active flag are used for select options. (So if you create a shipment order choose from the active verison of package type records) Long story short: i have to revision all property changes
Vp
Vp17mo ago
Create new action, do your logic in ->action() and it will be easy like this https://filamentphp.com/docs/2.x/admin/pages/actions#custom-forms
peterkeri
peterkeriOP17mo ago
ok, I try it, thanks! @.valpuia i have this:
->actions([
Tables\Actions\ViewAction::make(),
Tables\Actions\Action::make('versioned_edit')
->mountUsing(fn (Forms\ComponentContainer $form) => $form->fill())
->action(function (Model $record, array $data): void {
//$this->record->author()->associate($data['authorId']);
//$this->record->save();
})
->form([
Forms\Components\Section::make('Default data')
->columns([
'sm' => 1,
'md' => 2,
'xl' => 2
])
->schema([
Forms\Components\TextInput::make('name')
->required()
->string()
->maxLength(255),
Forms\Components\TextInput::make('description')
->nullable()
->string()
->maxLength(255),
]),
Forms\Components\Section::make('Meta data')
->relationship('meta')
->schema([
Forms\Components\KeyValue::make('data')
->required()
->label('Meta data')
])
])
])
->actions([
Tables\Actions\ViewAction::make(),
Tables\Actions\Action::make('versioned_edit')
->mountUsing(fn (Forms\ComponentContainer $form) => $form->fill())
->action(function (Model $record, array $data): void {
//$this->record->author()->associate($data['authorId']);
//$this->record->save();
})
->form([
Forms\Components\Section::make('Default data')
->columns([
'sm' => 1,
'md' => 2,
'xl' => 2
])
->schema([
Forms\Components\TextInput::make('name')
->required()
->string()
->maxLength(255),
Forms\Components\TextInput::make('description')
->nullable()
->string()
->maxLength(255),
]),
Forms\Components\Section::make('Meta data')
->relationship('meta')
->schema([
Forms\Components\KeyValue::make('data')
->required()
->label('Meta data')
])
])
])
Questions: - that is what you think? if yes: - how can i filled the form with data (now the form is empty)? - I got an error to $this->record: undefined property
Vp
Vp17mo ago
1. you have to put inside ->formFill(['name' => 'myname']) ref https://filamentphp.com/docs/2.x/admin/pages/actions#filling-default-data 2. dd($record) and check whether the data is coming or not..
peterkeri
peterkeriOP17mo ago
@.valpuia ok, i made the changes, now: - the edit form filled with data --> OK - the edited record set to inactive --> OK - the new record created -- OK problems: my main problem has NOT solved. As you see the key-value component use a relationship. This data has been updated too when I use this:
$record->is_active = 0;
$record->save();
$record->is_active = 0;
$record->save();
Here is the action:
->actions([
Tables\Actions\ViewAction::make(),
Tables\Actions\Action::make('versioned_edit')
->mountUsing(fn (Model $record, Forms\ComponentContainer $form) => $form->fill([
'name' => $record->name
]))
->action(function (Model $record, array $data): void {
$record->is_active = 0;
$record->save();

static::getModel()::create($data);
})
->form([
Forms\Components\Section::make('Default data')
->columns([
'sm' => 1,
'md' => 2,
'xl' => 2
])
->schema([
Forms\Components\TextInput::make('name')
->required()
->string()
->maxLength(255),
Forms\Components\TextInput::make('description')
->nullable()
->string()
->maxLength(255),
]),
Forms\Components\Section::make('Meta data')
->relationship('meta')
->schema([
Forms\Components\KeyValue::make('data')
->required()
->label('Meta data')
])
])
])
->actions([
Tables\Actions\ViewAction::make(),
Tables\Actions\Action::make('versioned_edit')
->mountUsing(fn (Model $record, Forms\ComponentContainer $form) => $form->fill([
'name' => $record->name
]))
->action(function (Model $record, array $data): void {
$record->is_active = 0;
$record->save();

static::getModel()::create($data);
})
->form([
Forms\Components\Section::make('Default data')
->columns([
'sm' => 1,
'md' => 2,
'xl' => 2
])
->schema([
Forms\Components\TextInput::make('name')
->required()
->string()
->maxLength(255),
Forms\Components\TextInput::make('description')
->nullable()
->string()
->maxLength(255),
]),
Forms\Components\Section::make('Meta data')
->relationship('meta')
->schema([
Forms\Components\KeyValue::make('data')
->required()
->label('Meta data')
])
])
])
Vp
Vp17mo ago
can you try ->dehydrated(false) inside keyValue, but not sure tho
peterkeri
peterkeriOP17mo ago
@.valpuia now the related data not updated --> it seems okay. i think only one thing left: the related data (meta stored in another table with hasOne relation) not created when i call static::getModel()::create($data) function for the new record
Vp
Vp17mo ago
yes, ->dehydrated(false) prevent those also.. When you said "relationship data update too", how it is update? I would suggest remove ->dehydrated(false) and put ->disabled() in every field, data will be update but not new value.. only updated_at column
peterkeri
peterkeriOP17mo ago
@.valpuia Before added ->dehydrated(false), if I called
$record->is_active = 0;
$record->save();
$record->is_active = 0;
$record->save();
the save() updated the meta property too (meta stored in another table with hasOne relation) in the database with the posted meta data (what is dirty or not) for the original record. I don't want it, I want update ONLY the is_active field. Now the meta data not udpated - as you said - beacuse of dehydration. i have to store all posted data into a new record, so i dont have to disable form element in the custom edit form (what i created for this action)
Vp
Vp17mo ago
"the save() updated the meta property too (meta stored in another table with hasOne relation) in the database with the posted meta data (what is dirty or not) for the original record." still I don't understand, my English is not great btw.. what kind of update are we talking about? Eg: If you have 'foo' => 'bar' in KeyValue.. then after edit then save, how is this foo-bar updated?
peterkeri
peterkeriOP17mo ago
Ok, just a sec
peterkeri
peterkeriOP17mo ago
@.valpuia
peterkeri
peterkeriOP17mo ago
I made a screencast of the whole process
Vp
Vp17mo ago
so you need to create new "meta" (relationship) when edit, and keeping the old as it is.. right?
peterkeri
peterkeriOP17mo ago
correct And i dont understand why updated because i use this:
$record->is_active = 0;
$record->save();
$record->is_active = 0;
$record->save();
As i know this need to update only is_active field
Vp
Vp17mo ago
yeah me too.. let me check
peterkeri
peterkeriOP17mo ago
i try to move the update part of my action to the after() function, but the same happened..
Vp
Vp17mo ago
Hi, @peterkeri I don't have any idea about relationship.. sorry
peterkeri
peterkeriOP17mo ago
nope, thanks for your time!
Vp
Vp17mo ago
Hi again, One more thing, if you can move out relationship field and store json column in the same table and it will work.. if you prefer
Want results from more Discord servers?
Add your server