Trying to dynamically disable file input, when checkbox is checked

Hi guys, I have this code that will make the favicon the same as the logo when the checkbox is checked. If this is checked I want to disable the file input for favicon. Don't worry about the TenantFileUpload it is exactly the same as FileUpload just with changed saving.
return [
TextInput::make('name')
->label('Name')
->required(),
ColorSwatchInput::make('primary_color')
->label('Primary Color')
->required(),
TenantFileUpload::make('logo')
->label('Logo')
->image()
->maxSize(2048) // 2MB
->maxFiles(1)
->live(),
Checkbox::make('logo_same_as_favicon')
->live()
->disabled(fn (Get $get) => empty($get('logo')))
->afterStateUpdated(function (bool $state, Set $set) {
if ($state) {
$set('favicon', []);
}
}),
TenantFileUpload::make('favicon')
->label('Favicon')
->helperText('A small icon that appears in the browser tab')
->image()
->maxSize(2048) // 2MB
->maxFiles(1)
->disabled(fn (Get $get) => $get('logo_same_as_favicon')),
];
}
return [
TextInput::make('name')
->label('Name')
->required(),
ColorSwatchInput::make('primary_color')
->label('Primary Color')
->required(),
TenantFileUpload::make('logo')
->label('Logo')
->image()
->maxSize(2048) // 2MB
->maxFiles(1)
->live(),
Checkbox::make('logo_same_as_favicon')
->live()
->disabled(fn (Get $get) => empty($get('logo')))
->afterStateUpdated(function (bool $state, Set $set) {
if ($state) {
$set('favicon', []);
}
}),
TenantFileUpload::make('favicon')
->label('Favicon')
->helperText('A small icon that appears in the browser tab')
->image()
->maxSize(2048) // 2MB
->maxFiles(1)
->disabled(fn (Get $get) => $get('logo_same_as_favicon')),
];
}
^^ this is code for the schema and this is the page below
3 Replies
Jpac14
Jpac14OP4w ago
use InteractsWithForms;
use WithFileUploads;

protected static ?string $navigationIcon = 'heroicon-o-paint-brush';

protected static ?string $navigationGroup = 'Settings';

protected static string $view = 'filament.tenant.pages.branding';

public ?array $data = [];

public function mount(): void
{
$this->form->fill([
'name' => tenant('name'),
'primary_color' => tenant('primary_color'),
'logo' => tenant('logo'),
'favicon' => tenant('favicon'),
]);
}

public function form(Form $form): Form
{
return $form->schema(BrandingForm::schema())->statePath('data');
}

public function submit()
{
$this->validate();

dd($this->data);

$logoUrl = $this->processImage($this->data['logo'], 'logos');
$faviconUrl = $this->processImage($this->data['favicon'], 'favicons');

tenant()->update([
'name' => $this->data['name'],
'primary_color' => $this->data['primary_color'],
'logo' => $logoUrl,
'favicon' => $faviconUrl,
]);

Notification::make()
->title('Branding updated')
->success()
->send();

$this->dispatch('reload');
}
use InteractsWithForms;
use WithFileUploads;

protected static ?string $navigationIcon = 'heroicon-o-paint-brush';

protected static ?string $navigationGroup = 'Settings';

protected static string $view = 'filament.tenant.pages.branding';

public ?array $data = [];

public function mount(): void
{
$this->form->fill([
'name' => tenant('name'),
'primary_color' => tenant('primary_color'),
'logo' => tenant('logo'),
'favicon' => tenant('favicon'),
]);
}

public function form(Form $form): Form
{
return $form->schema(BrandingForm::schema())->statePath('data');
}

public function submit()
{
$this->validate();

dd($this->data);

$logoUrl = $this->processImage($this->data['logo'], 'logos');
$faviconUrl = $this->processImage($this->data['favicon'], 'favicons');

tenant()->update([
'name' => $this->data['name'],
'primary_color' => $this->data['primary_color'],
'logo' => $logoUrl,
'favicon' => $faviconUrl,
]);

Notification::make()
->title('Branding updated')
->success()
->send();

$this->dispatch('reload');
}
If someone could try reproduce this that would be great. It disables a text input but when I link it to a file input it fails to disable it. Any help appreciated thanks Bump!
Ava
Ava4w ago
Hey @Jpac14 It looks like the issue might be related to how the TenantFileUpload component processes the disabled() logic dynamically. File inputs in Filament don’t always respond the same way as text inputs when state changes, which could be why your checkbox logic isn’t working as expected. Give this a try, its just my two cents so it may or may not work.
return [
TextInput::make('name')
->label('Name')
->required(),
ColorSwatchInput::make('primary_color')
->label('Primary Color')
->required(),
TenantFileUpload::make('logo')
->label('Logo')
->image()
->maxSize(2048)
->maxFiles(1)
->live(),
Checkbox::make('logo_same_as_favicon')
->label('Use Logo as Favicon')
->live()
->disabled(fn (Get $get) => empty($get('logo')))
->afterStateUpdated(function (bool $state, Set $set) {
if ($state) {
$set('favicon', []); // Clear favicon when checkbox is checked
}
}),
TenantFileUpload::make('favicon')
->label('Favicon')
->helperText('A small icon that appears in the browser tab')
->image()
->maxSize(2048)
->maxFiles(1)
->extraAttributes([
'x-bind:disabled' => "state.logo_same_as_favicon", // Dynamically disable using Alpine.js
]),
];
return [
TextInput::make('name')
->label('Name')
->required(),
ColorSwatchInput::make('primary_color')
->label('Primary Color')
->required(),
TenantFileUpload::make('logo')
->label('Logo')
->image()
->maxSize(2048)
->maxFiles(1)
->live(),
Checkbox::make('logo_same_as_favicon')
->label('Use Logo as Favicon')
->live()
->disabled(fn (Get $get) => empty($get('logo')))
->afterStateUpdated(function (bool $state, Set $set) {
if ($state) {
$set('favicon', []); // Clear favicon when checkbox is checked
}
}),
TenantFileUpload::make('favicon')
->label('Favicon')
->helperText('A small icon that appears in the browser tab')
->image()
->maxSize(2048)
->maxFiles(1)
->extraAttributes([
'x-bind:disabled' => "state.logo_same_as_favicon", // Dynamically disable using Alpine.js
]),
];
I am thinking that by adding the extraAttributes property, you can use Alpine.js (x-bind) to directly control the disabled attribute on the file input. This works should dynamically with your checkbox state and avoids limitations with Filament's built-in logic. ofc, you will also need to make sure that Alpine.js is included in your project.
Jpac14
Jpac14OP4w ago
Hi Ava, I tried this but it didn't work. Maybe FileUpload doesn't work very well with dynamically disabling. Not sure if this will help, but here is the code for TenantFIleUpload it is almost identical to FileUpload
class TenantFileUpload extends FileUpload
{
protected function setUp(): void
{
parent::setUp();

// Override file retrieval logic to use tenant_asset
$this->getUploadedFileUsing(static function (TenantFileUpload $component, string $file, string | array | null $storedFileNames): ?array {
try {
$url = tenant_asset($file); // Use tenant_asset to resolve the URL
} catch (Throwable $exception) {
return null;
}

return [
'name' => ($component->isMultiple() ? ($storedFileNames[$file] ?? null) : $storedFileNames) ?? basename($file),
'size' => $component->getDisk()->size($file),
'type' => $component->getDisk()->mimeType($file),
'url' => $url,
];
});
}
}
class TenantFileUpload extends FileUpload
{
protected function setUp(): void
{
parent::setUp();

// Override file retrieval logic to use tenant_asset
$this->getUploadedFileUsing(static function (TenantFileUpload $component, string $file, string | array | null $storedFileNames): ?array {
try {
$url = tenant_asset($file); // Use tenant_asset to resolve the URL
} catch (Throwable $exception) {
return null;
}

return [
'name' => ($component->isMultiple() ? ($storedFileNames[$file] ?? null) : $storedFileNames) ?? basename($file),
'size' => $component->getDisk()->size($file),
'type' => $component->getDisk()->mimeType($file),
'url' => $url,
];
});
}
}
If you have any other ideas let me know. Thanks, Jpac14

Did you find this page helpful?