Form Columns Variable/Dynamic

To my chagrin there is no closure available to Form's columns I'm using Group/Sections with ->column() And really need the ability to change the column numbers dynamically. Any idea how to set a form column value dynamically?
18 Replies
LeandroFerreira
What about the array? The tailwind breakpoints?
bionary
bionaryOP2y ago
not sure what you mean, sorry @Leandro Ferreira If I could get ahead of the data and set a variable and then access it in columns I could do this, but I'm not sure how The resource uses public static function form(Form $form): Form { so I'm not sure how to intercept the model data and set some kind of value
LeandroFerreira
I'm thinking about it:
Section::make('Heading')
->columns([
'default' => 1,
'sm' => 3,
'xl' => 6,
'2xl' => 8,
])
->schema([
//
]),
Section::make('Heading')
->columns([
'default' => 1,
'sm' => 3,
'xl' => 6,
'2xl' => 8,
])
->schema([
//
]),
bionary
bionaryOP2y ago
I need to explicitly change a column from 3 to 2 when I am hiding one of my form elements (which is a custom / image type) when the image is not there it looks horrible...giant empty space odd there is no callback on ->columns() considering there are callbacks most everywhere else like:
->visible(function($record){
...
}),
->visible(function($record){
...
}),
LeandroFerreira
My bad I understood now
bionary
bionaryOP2y ago
perhaps there is another solution I'm not thinking about
LeandroFerreira
maybe extraAttributes... Can you share the screenshot/code please? you can try ->extraAttributes() I'm not sure
bionary
bionaryOP2y ago
//resource
Group::make([
ViewField::make('image')->label('Legacy Image')->view('filament.forms.image')
->visible(function($record){
//Only show legacy image if the preview_image is null
return is_null($record->preview_image) && !empty($record->image);
}),
//resource
Group::make([
ViewField::make('image')->label('Legacy Image')->view('filament.forms.image')
->visible(function($record){
//Only show legacy image if the preview_image is null
return is_null($record->preview_image) && !empty($record->image);
}),
//view
<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()"
>
<?php
$imgUrl=null;

//Only show legacy image if the preview_image is null
if ( is_null($this->record->preview_image) && $this->record->image) {
$imgUrl = Illuminate\Support\Facades\Storage::disk('legacy.gallery')->url($this->record->image);
}
?>
@if($imgUrl)
<img src="{{ $imgUrl }}" style="max-height: 260px;">
@endif

</x-dynamic-component>
//view
<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()"
>
<?php
$imgUrl=null;

//Only show legacy image if the preview_image is null
if ( is_null($this->record->preview_image) && $this->record->image) {
$imgUrl = Illuminate\Support\Facades\Storage::disk('legacy.gallery')->url($this->record->image);
}
?>
@if($imgUrl)
<img src="{{ $imgUrl }}" style="max-height: 260px;">
@endif

</x-dynamic-component>
it's a long story but I inherited a legacy project and need a way to show the "old" image but provide a new field for uploading the "new" image And support uploading of Tiff files. (like I said...very long story) once the "new" image has been uploaded, the "old" image field can be hidden from any forms from that point forward It all works fine, except for this last column issue
LeandroFerreira
What about the number of columns... can you show me the issue?
bionary
bionaryOP2y ago
screenshot?
LeandroFerreira
yep
bionary
bionaryOP2y ago
bionary
bionaryOP2y ago
oh wait a second...maybe I can use ->colSpan()! I think that accepts a closure eh, no good the problem still resides with ->column(int) changing the ->columnSpan() merely stacks the images My lame-o solution is to move the center (empty) image/column to the rightmost position. When it is null/empty it looks slightly better then the giant hole in the middle. I guess I'm going with that for now.
LeandroFerreira
I'll check if it is possible and I let you know
bionary
bionaryOP2y ago
I got it working a bit better with ->columnSpan() I was setting ->columns(1) explicitly... I removed that and put my logic inside ->columnSpan() What happens now is the "new" image will take up 2/3 of the columns when the "old" image is null. I was hoping to change the columns down to 2 in that case...but I guess this runner up solution is okay too.
->columnSpan(function($record){
//Only show legacy image if the preview_image is null
return (is_null($record->preview_image) && !empty($record->image))? 1 : 2;
}),
->columnSpan(function($record){
//Only show legacy image if the preview_image is null
return (is_null($record->preview_image) && !empty($record->image))? 1 : 2;
}),
LeandroFerreira
Nice. I thought something like this:
->columnSpan(fn ($component) => $component->getContainer()->getComponent('data.image') ? 1 : 2)
->columnSpan(fn ($component) => $component->getContainer()->getComponent('data.image') ? 1 : 2)
bionary
bionaryOP2y ago
that does indeed work I went for a walk and reflected upon this. I came up with a solution that alternates between my desired 2 columns and 3 columns based on conditions. I set total columns to a "common denominator" in this case 6. Then I dynamically change the ->columnSpan() of each Group to either 2 or 3. That gives me 3 columns and 2 columns respectively. It's not the most elegant code-wise in that I need to add the same code block in several different places but it does do precisely what I was hoping it would do!
awcodes
awcodes2y ago
Honestly, I think you’re way overthinking this. Just use three columns and use a placeholder for the second column that is only visible when the state is null. That way there’s no UX shifting. I have similar situation where I have pages that use a block builder, but content managers need to update Seo things about a page whose content may be hard coded. So on those pages I show a placeholder instead on the block builder. So the overall page in the admin doesn’t actually change.
Want results from more Discord servers?
Add your server