F
Filamentβ€’11mo ago
John

Passing multiple variables to a ViewField

What I'm using now:
ViewField::make('myViewField')
->formatStateUsing(function ($record) {
return [
'href' => route('requests.pdf', ['request' => $record]),
'caption' => __('request.pdf.link')
];
})
->view('forms.components.download')
ViewField::make('myViewField')
->formatStateUsing(function ($record) {
return [
'href' => route('requests.pdf', ['request' => $record]),
'caption' => __('request.pdf.link')
];
})
->view('forms.components.download')
<x-dynamic-component
:component="$getFieldWrapperView()"
:id="$getId()"
:label="$getLabel()"
:label-sr-only="$isLabelHidden()"
:helper-text="$getHelperText()"
:hint="$getHint()"
:hint-action="$getHintAction()"
:hint-color="$getHintColor()"
:hint-icon="$getHintIcon()"
:required="$isRequired()"
:state-path="$getStatePath()"
>
<div x-data="{ state: $wire.entangle('{{ $getStatePath() }}').defer }">
<a href="{{ $getState()['href'] }}" class="flex gap-1">
<x-icon-gmdi-file-download-o class="w-6 h-6"/>{{ $getState()['caption'] }}
</a>
</div>
</x-dynamic-component>
<x-dynamic-component
:component="$getFieldWrapperView()"
:id="$getId()"
:label="$getLabel()"
:label-sr-only="$isLabelHidden()"
:helper-text="$getHelperText()"
:hint="$getHint()"
:hint-action="$getHintAction()"
:hint-color="$getHintColor()"
:hint-icon="$getHintIcon()"
:required="$isRequired()"
:state-path="$getStatePath()"
>
<div x-data="{ state: $wire.entangle('{{ $getStatePath() }}').defer }">
<a href="{{ $getState()['href'] }}" class="flex gap-1">
<x-icon-gmdi-file-download-o class="w-6 h-6"/>{{ $getState()['caption'] }}
</a>
</div>
</x-dynamic-component>
This works just fine. Just wondering if others are doing / would do this differently...
6 Replies
Patrick Boivin
Patrick Boivinβ€’11mo ago
This is fine. A minor thing that comes to mind: ViewField is really meant to create a custom field, and make its $state available as part of the submitted form values. If you don't need that, you could use the more simple View component instead, and pass any extra data with ->viewData([ ... ])
John
Johnβ€’10mo ago
Ah, I didn't know the View component. Couldn't find it in the v2 docs either. I tried it, but ->viewData() can't handle a closure, so I'm unable to create the route using the current record.
Patrick Boivin
Patrick Boivinβ€’10mo ago
I think there's a way, let me see I think you could use $getRecord() in the view directly Or if you really need to pass a closure, something to try:
->viewData([
'something' => fn ($record) => /* ... */,
])

{{ $this->evaluate($something) }}
->viewData([
'something' => fn ($record) => /* ... */,
])

{{ $this->evaluate($something) }}
But if ->viewData() is getting out of hand, it's probably a good opportunity to create a custom view component instead...
John
Johnβ€’10mo ago
I can use $getRecord() in the view. But I'd rather give the full route from the form schema. I like the closure + evaluate approach! But it gives me evaluate does not exist on my class RequestWorkflow extends Page implements HasForms. Which I don't really understand. I guess evaluate() should end up in my component? (I'm happy to revert to the ViewField I had before. This is just for learning Filament and its internals πŸ™‚ )
Patrick Boivin
Patrick Boivinβ€’10mo ago
Yeah I think I got it wrong ($this is probably not the right thing in the current context), but you can call ->evaluate() on the Field object.
John
Johnβ€’10mo ago
I tried a bunch to replace $this with, none worked. $field->evaluate($href) doesn't complain, but returns nothing. $component->evaluate($href) gives Call to undefined method Illuminate\View\DynamicComponent::evaluate(). What does work is accessing the closure like this in the view: {{ $href($getRecord()) }} but it's less flexible. I'm back to making it specific in the view.