FilamentF
Filamentβ€’3y ago
Husky110

Selfupdating Modal-Form

Hi - I migrate my old frontend to filament and stumbled on a problem. Given the following scenario: I have a resource that manages a Model (A) and I made an Edit-Action for model A. Now A has a BelongsTo-Relationship to another model (B) and a BelongsToMany-Relationship (with pivot-values) to yet another model (C) and C has a BelongsTo-Relationship to B. Model C is the interesting part here, since it stores templates for dynamic configurations of A (with "dynamic" I mean that it stores a config-key, a type like text-input or select and some template-data).
What I want to have is a Select which updates the BelongsTo-B-relationship (pretty easy) but that also updates the form to show all relevant C-entries and make them editable. This might sound a bit confusing, so I've added a small demonstration. Whats happening in there is that when "Kein Fulfiller" is set, the model_b_id in A is set to null, when it is set to "FF-2222" the model_b_id is set to 2 -> But here is the catch: It is NOT updated in the DB until "Speichern" has been clicked. In the background happens an ajax-request via JQuery that loads the C-entries which correspond to B and displays them. When the user is done with it's edits, the user clicks "Speichern" and then everything is stored. I have no idea where to begin this. So how can I achieve the behavior in the demonstration in filament?
Peek_2023-07-26_17-40.gif
Solution
Okay - for anyone reading this: I can't share my code here directly, but I can write what I did in the end.
Within the form()-function I wrote a callback that loads all static form-components and added ->reactive() to the Select-Component that controls model_b_id in my Model A-Entry (let's just call it "Joe" for fun πŸ˜„ ). Still within the callback-function I've added all form-element-templates (Model C in my example) and stored them in a Model-B-ID-indexed array -> make sure you use the '.'-syntax here (like myGroupedItems.$myCustomTemplate->id.value), since this can be used later to call Laravel's ->sync()-function within the ->action()-function to work like this: $modelA->modelCBelongsToManyRelationship()->sync($data['myGroupedItems'])). The array is like this: $groups = ['1' => [*myItemsForModel-B-Entry-1], 2=> ...]. Then (still within the form-callback) I grouped them together like this and added a visable function:
foreach ($groups as $key => $items){
  $retval[] = Forms\Components\Group::make($items)
  ->visible(fn(callable $get) => $get('model_b_id') == $key);
}

This makes the modal updates itself, whenever the value of Joe changes. Now to have the values beeing loaded when the modal opens, I've created a callback-function within ->mountUsing() filling all the form-fields. And last-but-not-least added the data-storage (see above) and the whole thing was done.
I will mark this as a solution for now to give the thread an end, but tbh I am not really happy with this, since it would be cooler to have a callback on Joe himself that can alter the whole form. If someone finds a way to do this within the EditAction::make()-spectrum of a resource, feel free to add (and ping me please). πŸ™‚
Warning: This thing seems to ignore ModelPolicies! Make sure to make it only availble to the appropiate users (->visible() on the action itself helps)
Was this page helpful?