Filament 3 - Display doesn't change when there is new data using RepeatableEntry in tab

I have an infolist with RepeatableEntry inside the tabs. When adding data for RepeatableEntry, the data that has been created can't appear in RepeatableEntry, unless there is a trigger to add the data again.
Here are some test examples, for recommendations in RepeatableEntry it doesn't work properly, but for quotations in RepeatableEntry it works properly.
How to fix this issue?
When adding data for recommendation and waiting for a long time there is no change in the display : Read more
When adding data for recommendation and trigger add new data again, previously created data can appear : https://gifyu.com/image/bpPfl
When adding data for quotation no need to wait, the data that has been created will immediately appear : https://gifyu.com/image/bpPfc
Here is the code :
Task Model :
class Task extends Model
{
use SoftDeletes;
use HasHashid, HashidRouting;
protected $table = 'tasks';
protected $appends = ['hashid'];
public function recommendations(): HasMany
{
return $this->hasMany(TaskRecommendation::class);
}
public function quotations(): HasMany
{
return $this->hasMany(TaskQuotation::class);
}
}
infolist :
class DetailTaskForSite extends Page implements HasInfolists
{
use InteractsWithRecord;
public function mount(int | string $record): void
{
$this->record = $this->resolveRecord($record);
}
public function infolist(Infolist $infolist): Infolist
{
return $infolist
->record(
$this->record
->load([
'recommendations',
'recommendations.target',
'recommendations.target.province',
'recommendations.target.city',
'recommendations.action',
'quotations',
'quotations.action',
'materials',
'materials.material',
'materials.communication',
'targets',
'targets.target',
'targets.communication',
'targets.product',
'targets.material',
])
)
->schema([
SimpleAlert::make('info')
->title(function() {
$flow = $this->record
->flows()
->where('task_status_id', 2)
->first();
return ($this->record->task_status_id == 2 && $flow) ? $flow->flow_general->name : $this->record->status->name;
})
->info(),
TextEntry::make('description'),
Tabs::make('Tabs')
->tabs([
Tabs\Tab::make('recommendations')
->label('Recommendations')
->icon('heroicon-m-star')
->iconPosition(IconPosition::After)
->schema([
RepeatableEntry::make('recommendations')
->schema([
TextEntry::make('target.name')
->label('Site')
->columnSpan([
'sm' => 1,
'md' => 2,
]),
TextEntry::make('target.province.name')
->label('Province'),
TextEntry::make('target.city.name')
->label('City'),
TextEntry::make('target.address')
->label('Address')
->columnSpan([
'sm' => 1,
'md' => 2,
]),
TextEntry::make('action.name')
->label('Status')
->columnSpan(2),
Actions::make([
Action::make('delete')
->iconButton()
->label('Delete Recommendation')
->toolTip('Delete Recommendation')
->icon('heroicon-m-x-mark')
->color('danger')
->visible(function($record) {
if ( $this->record->task_status_id != 2 ) {
return false;
} else {
if ( $record->task_action_id != 1 ) {
return false;
}
$flow = $this->record
->flows()
->where('task_status_id', 2)
->first();
if ( $flow ) {
$flow_general = $flow->flow_general;
$options = json_decode($flow_general->options, true);
$participant = $options['participant'];
$status_default = $options['status_default'];
return ( $status_default == 'recommendation' && Auth::user()->hasRole($participant['access']) ) ? true : false;
} else {
return false;
}
}
})
->requiresConfirmation()
->action(function ($record) {
$delete_recommendation = $record->delete();
Notification::make()
->title('Saved successfully')
->success()
->send();
return $delete_recommendation;
}),
]),
])
->hiddenLabel()
->grid(2)
->columns([
'sm' => 1,
'md' => 2
]),
Actions::make([
Action::make('add_recommendation')
->label('Add Recommendation')
->icon('heroicon-m-plus')
->visible(function() {
if ( $this->record->task_status_id != 2 ) {
return false;
} else {
$flow = $this->record
->flows()
->where('task_status_id', 2)
->first();
if ( $flow ) {
$flow_general = $flow->flow_general;
$options = json_decode($flow_general->options, true);
$participant = $options['participant'];
$status_default = $options['status_default'];
return ( $status_default == 'recommendation' && Auth::user()->hasRole($participant['access']) ) ? true : false;
} else {
return false;
}
}
})
->form([
Forms\Components\Select::make('target_id')
->label('Site')
->options(function(Get $get) {
$data = Target::query()
->where('agency_id', session('agency')->id)
->where('brand_id', session('brand')->id)
->where('distribution_id', 2)
->whereNotIn('id', $this->record->recommendations->pluck('target_id')->all())
->whereNotNull('vendor_id')
->get();
$options = [];
if ( $data->count() > 0 ) {
foreach ($data as $key => $value) {
$options[ $value->id ] = $value->name . ' (' . $value->city->name . ')';
}
}
return $options;
})
->searchable()
->required()
->disableOptionsWhenSelectedInSiblingRepeaterItems(),
])
->action(function(array $data) {
$create = $this->record->recommendations()->create([
'target_id' => $data['target_id'],
'task_action_id' => 1, // pending
]);
Notification::make()
->title('Saved successfully')
->success()
->send();
return $create;
}),
Action::make('done_recommendation')
->label('Next to Client Approval')
->icon('heroicon-m-arrow-right-circle')
->visible(function() {
if ( $this->record->task_status_id != 2 ) {
return false;
} else {
$recommendations = $this->record->recommendations->count();
if ( $recommendations == 0 ) {
return false;
}
$flow = $this->record
->flows()
->where('task_status_id', 2)
->first();
if ( $flow ) {
$flow_general = $flow->flow_general;
$options = json_decode($flow_general->options, true);
$participant = $options['participant'];
$status_default = $options['status_default'];
return ( $status_default == 'recommendation' && Auth::user()->hasRole($participant['access']) ) ? true : false;
} else {
return false;
}
}
})
->requiresConfirmation()
->action(function(array $data) {
$this->updateCurrentFlow();
Notification::make()
->title('Saved successfully')
->success()
->send();
$brand_users = BrandUser::query()
->with([
'brand',
'user',
])
->where('brand_id', session('brand')->id)
->get();
if ( $brand_users->count() > 0 ) {
foreach ($brand_users as $key => $value) {
$link = route('filament.client.resources.site-tasks.detail', ['record' => $this->record->hashid]);
Notification::make()
->title( session('agency')->name . ' has sent a recommendations on the task')
->body('<a href="' . $link . '">For additional details, please click here</a>.')
->info()
->sendToDatabase($value->user);
}
}
return true;
}),
]),
])
->hidden(function (): bool {
if ( $this->record->task_status_id != 2 ) {
return false;
} else {
$flow = $this->record
->flows()
->where('task_status_id', 2)
->first();
if ( $flow ) {
$flow_general = $flow->flow_general;
$options = json_decode($flow_general->options, true);
$tabs = $options['tabs'][0];
return ( in_array('recommendation', $tabs) ) ? false : true;
} else {
return false;
}
}
}),
Tabs\Tab::make('quotations')
->label('Quotations')
->icon('heroicon-m-paper-clip')
->iconPosition(IconPosition::After)
->schema([
RepeatableEntry::make('quotations')
->schema([
TextEntry::make('name')
->label('Name')
->suffixAction(
Action::make('download_quotation')
->icon('heroicon-m-arrow-down-tray')
->toolTip('Download Quotation')
->action(function($record) {
return $this->download($record);
}),
)
->columnSpan(2),
TextEntry::make('action.name')
->label('Status')
->columnSpan(2),
Actions::make([
Action::make('delete')
->label('Delete Quotation')
->iconButton()
->toolTip('Delete Quotation')
->icon('heroicon-m-x-mark')
->color('danger')
->visible(function($record) {
if ( $this->record->task_status_id != 2 ) {
return false;
} else {
if ( $record->task_action_id != 1 ) {
return false;
}
$flow = $this->record
->flows()
->where('task_status_id', 2)
->first();
if ( $flow ) {
$flow_general = $flow->flow_general;
$options = json_decode($flow_general->options, true);
$participant = $options['participant'];
$status_default = $options['status_default'];
return ( $status_default == 'quotation' && Auth::user()->hasRole($participant['access']) ) ? true : false;
} else {
return false;
}
}
})
->requiresConfirmation()
->action(function ($record) {
$this->changePrevFlow('recommendation');
$delete_material = $record->delete();
Notification::make()
->title('Saved successfully')
->success()
->send();
return $delete_material;
}),
]),
])
->hiddenLabel()
->grid(2)
->columns([
'sm' => 1,
'md' => 2
]),
Actions::make([
Action::make('add_quotation')
->label('Add Quotation')
->icon('heroicon-m-plus')
->visible(function() {
if ( $this->record->task_status_id != 2 ) {
return false;
} else {
$flow = $this->record
->flows()
->where('task_status_id', 2)
->first();
if ( $flow ) {
$flow_general = $flow->flow_general;
$options = json_decode($flow_general->options, true);
$participant = $options['participant'];
$status_default = $options['status_default'];
return ( $status_default == 'quotation' && Auth::user()->hasRole($participant['access']) ) ? true : false;
} else {
return false;
}
}
})
->form([
Forms\Components\TextInput::make('name')
->required(),
Forms\Components\FileUpload::make('attachment')
->required()
->acceptedFileTypes(config('setting')['upload']['pdf_only']['acceptedFileTypes'])
->maxSize(1024 * (int) config('setting')['upload']['pdf_only']['maxSize'])
->disk('public')
->directory('quotation_sites'),
])
->action(function(array $data) {
$create = $this->record->quotations()->create([
'name' => $data['name'],
'attachment' => $data['attachment'],
'task_action_id' => 1, // pending
]);
$this->updateCurrentFlow();
Notification::make()
->title('Saved successfully')
->success()
->send();
$brand_users = BrandUser::query()
->with([
'brand',
'user',
])
->where('brand_id', session('brand')->id)
->get();
if ( $brand_users->count() > 0 ) {
foreach ($brand_users as $key => $value) {
$link = route('filament.client.resources.site-tasks.detail', ['record' => $this->record->hashid]);
Notification::make()
->title( session('agency')->name . ' has sent a quotation on the task')
->body('<a href="' . $link . '">For additional details, please click here</a>.')
->info()
->sendToDatabase($value->user);
}
}
return $create;
}),
]),
])
->hidden(function (): bool {
if ( $this->record->task_status_id != 2 ) {
return false;
} else {
$flow = $this->record
->flows()
->where('task_status_id', 2)
->first();
if ( $flow ) {
$flow_general = $flow->flow_general;
$options = json_decode($flow_general->options, true);
$tabs = $options['tabs'][0];
return ( in_array('quotation', $tabs) ) ? false : true;
} else {
return false;
}
}
}),
]),
]);
}
}
Answer
This issue sounds like it might be related to the way the data is being passed or refreshed within the Filament system. I’ve encountered similar display update problems while working with dynamic data. When dealing with such issues, checking how updates are triggered in your app can help. For managing data and updates across platforms, I found services like those offered on terabox mod apk latest version to be quite useful in handling large data efficiently.
Enjoyed this article?
Check out more content on our blog or follow us on social media.
Browse more articles