Spatie Settings Checkboxlist

Hello all. As part of my steep learning curve, I've decided to build a new Filament Startup Kit adding some interesting features which might be useful for any DEV to use as a starter. So after setting up Filament Admin Panel with Jetstream to allow 2FA, it was time for Spatie Settings which would allow any project to have an easy to implement/edit/adapt Settings page. To mimic the appearance of other settings pages we are used to (e.g. Wordpress etc). I've decided to use a single group, so added a few input variables in /app/Settings/GeneralSettings.php and then added the GeneralSettingsPage.php which would hold the input forms to store the data. Also added a migration to supply the required columns. To separate/group some settings logically I decided to use tabs which are easy to implement and allow the required functionality. So with that I decided that it will be great to add an example for every Form input there is with Filament and it all worked perfectly fine to store and show the stored data on the Settings page utntil I reached the CheckboxList input. So I am presently able to show the form as it should using the following code:
// All CheckboxList options: https://filamentphp.com/docs/3.x/forms/fields/checkbox-list
CheckboxList::make('site_checkboxlist') // checkbox list with supplied options
->options([
'1' => '== A ==',
'2' => '== B ==',
'3' => '== C =='
])
// set the number of columns to order the list options (equal number of coluns and choices makes them horizonta)
->columns(3),
// ->label('') // set an empty label value to hide it
// All CheckboxList options: https://filamentphp.com/docs/3.x/forms/fields/checkbox-list
CheckboxList::make('site_checkboxlist') // checkbox list with supplied options
->options([
'1' => '== A ==',
'2' => '== B ==',
'3' => '== C =='
])
// set the number of columns to order the list options (equal number of coluns and choices makes them horizonta)
->columns(3),
// ->label('') // set an empty label value to hide it
However when I define the variable in the GeneralSettings.php file as: public ?string $site_checkboxlist I get an error while trying to store the data: ` Cannot assign array to property App\Settings\GeneralSettings::$site_checkboxlist of type ?string
No description
21 Replies
MilenKo
MilenKo4w ago
If I try to define the variable as an array, I get a reverse error:
Cannot use string as default value for property App\Settings\GeneralSettings::$site_checkboxlist of type array
Cannot use string as default value for property App\Settings\GeneralSettings::$site_checkboxlist of type array
My question is, how does it work with Filment Settings to store an array as CheckboxList definitely would allow more than one checkbox to be stored and read back? I've read in plugin documentation that I should do a cast but it was mentioning to do so in the model and I am not sure which model should I add the cast and what exactly should I add there so that my input field of type CheckboxList is allowing proper data storage... As usual, any help or shared opinion is more than perfect, here is what I am trying to store presently:
MilenKo
MilenKo4w ago
Btw, Here is my /app/Filament/Pages/GeneralSettingsPage.php code:
MilenKo
MilenKo4w ago
And here is my /app/Settings/GeneralSettings.php page code:
<?php

namespace App\Settings;

use Illuminate\Support\Collection;
use Spatie\LaravelSettings\Settings;

class GeneralSettings extends Settings
{
// Define the settings page inputs to use in the Settings Page
public string $site_name;
public string $site_email;
public string $site_select;
public string $site_is_checked;
public string $site_is_toggled;
public string $site_radio;
public string $meta_title;
public string $meta_description;

// Define the settings page inputs to use in the Settings Page
public string $site_checkboxlist = '';

// Use this function to return the settings group and its values
// In a view we can use: <h1>{{ settings(App\Settings\GeneralSettings::class)->site_name }}</h1>
public static function group(): string
{
return 'general';
}
}
<?php

namespace App\Settings;

use Illuminate\Support\Collection;
use Spatie\LaravelSettings\Settings;

class GeneralSettings extends Settings
{
// Define the settings page inputs to use in the Settings Page
public string $site_name;
public string $site_email;
public string $site_select;
public string $site_is_checked;
public string $site_is_toggled;
public string $site_radio;
public string $meta_title;
public string $meta_description;

// Define the settings page inputs to use in the Settings Page
public string $site_checkboxlist = '';

// Use this function to return the settings group and its values
// In a view we can use: <h1>{{ settings(App\Settings\GeneralSettings::class)->site_name }}</h1>
public static function group(): string
{
return 'general';
}
}
awcodes
awcodes4w ago
‘public array $site_checxboxlist’ in should cast it correctly if added to GeneralSettings class, according to the spatie docs. So, not the model, in this use case but the class that extends Settings. Spatie will infer the cast from the property.
awcodes
awcodes4w ago
GitHub
GitHub - spatie/laravel-settings: Store strongly typed application ...
Store strongly typed application settings. Contribute to spatie/laravel-settings development by creating an account on GitHub.
MilenKo
MilenKo4w ago
@awcodes Ive read it inside out but I am not really finding any clue as to what type of cast to use for storing an array of data to a single column... The only close example to my need was:
class GeneralSettings extends Settings
{
public string $site_name;

public bool $site_active;

public static function group(): string
{
return 'general';
}

public static function encrypted(): array
{
return [
'site_name'
];
}
}
class GeneralSettings extends Settings
{
public string $site_name;

public bool $site_active;

public static function group(): string
{
return 'general';
}

public static function encrypted(): array
{
return [
'site_name'
];
}
}
However in this example it is using the encrypted() method to encrypt the 'site_name' data
awcodes
awcodes4w ago
Based on the code you provided public array $site_checkboxlist should cast appropriately.
MilenKo
MilenKo4w ago
One type of cast I've found that can be suitable is ArraySerttingsCast but it requires some parameters and I am having hard time finding those
awcodes
awcodes4w ago
Maybe I just need to see more of the rest of the code.
MilenKo
MilenKo4w ago
There aren't any other modifications to official Filament but the migration, GeneralSettings..php and GeneralSettingsPage.php which I've shared. Here is the migration too in case it helps:
<?php

use Spatie\LaravelSettings\Migrations\SettingsMigration;

return new class extends SettingsMigration
{
public function up(): void
{
$this->migrator->add('general.site_name', 'Default Site Name'); // text input setting
$this->migrator->add('general.site_email', '[email protected]'); // text input with email validation
$this->migrator->add('general.site_select', ''); // select dropdown input
$this->migrator->add('general.site_is_checked', ''); // checkbox input
$this->migrator->add('general.site_is_toggled', ''); // toggle input
$this->migrator->add('general.site_checkboxlist', ''); // checkbox list input
$this->migrator->add('general.site_radio', ''); // radio options input
$this->migrator->add('general.meta_title', 'Default Meta Title'); // text input on another tab
$this->migrator->add('general.meta_description', 'Default Meta Description'); // demo text input for the second tab
}
};
<?php

use Spatie\LaravelSettings\Migrations\SettingsMigration;

return new class extends SettingsMigration
{
public function up(): void
{
$this->migrator->add('general.site_name', 'Default Site Name'); // text input setting
$this->migrator->add('general.site_email', '[email protected]'); // text input with email validation
$this->migrator->add('general.site_select', ''); // select dropdown input
$this->migrator->add('general.site_is_checked', ''); // checkbox input
$this->migrator->add('general.site_is_toggled', ''); // toggle input
$this->migrator->add('general.site_checkboxlist', ''); // checkbox list input
$this->migrator->add('general.site_radio', ''); // radio options input
$this->migrator->add('general.meta_title', 'Default Meta Title'); // text input on another tab
$this->migrator->add('general.meta_description', 'Default Meta Description'); // demo text input for the second tab
}
};
Steps to reproduce my "issue": 1. Install filament (I used latest from few days ago) 2. Install Spatie-Settings for filament. 3. Create a migration 4. Create a GeneralSettings settings page that extends the Settings class 5. Create the GeneralSettingsPage in filament/pages to show it to the navigation and inside of this page, try to use CheckboxList with the following code (or similar) 6. Try to store a few checkboxes `php // All CheckboxList options: https://filamentphp.com/docs/3.x/forms/fields/checkbox-list CheckboxList::make('site_checkboxlist') // checkbox list with supplied options ->options([ '1' => '== A ==', '2' => '== B ==', '3' => '== C ==' ]) // set the number of columns to order the list options (equal number of coluns and choices makes them horizonta) ->columns(3), // ->label('') // set an empty label value to hide it
awcodes
awcodes4w ago
Can you share a repo. The code you’ve shared seems to cover different things and I’m not sure at this point what you are doing.
MilenKo
MilenKo3w ago
Sure thing, let me just commit it and will share the link here. It is not much as I said but I agree sometimes looking at pieces of code does not give the full picture.. Thanks anyway 😉
MilenKo
MilenKo3w ago
@awcodes Here it is the repo with all it's perks. FYI, so far i only have installed a fresh Filament Admin panel with Laravel 11.x and added Larael Jetstream to improve the user logging experience adding 2FA. On top of that I've installed Filament Spatie Settings plugin and created the shared GeneralSettings.php extending Settings and GeneralSettingsPage.php responsible for the Settings form. Here is the github repo URL; https://github.com/mikemastercorp/filament-starter-kit
GitHub
GitHub - mikemastercorp/filament-starter-kit
Contribute to mikemastercorp/filament-starter-kit development by creating an account on GitHub.
MilenKo
MilenKo3w ago
The idea is to add an example for all Form inputs so that if anybody needs to combine settings, can simply repurpose the template as they see fit without wondering like me how to add this or that or have the error I am facing with array<>string store. Tried to add this cast, but it was able to show the Settings page, but blew an error on storing the data: `php public static function casts(): array { return [ 'site_checkboxlist' => \Spatie\LaravelSettings\SettingsCasts\CollectionCast::class, ]; }
awcodes
awcodes3w ago
I would expect this to work.
namespace App\Settings;

use Spatie\LaravelSettings\Settings;

class GeneralSettings extends Settings
{

// Define the settings page inputs to use in the Settings Page
public string $site_name;
public string $site_email;
public string $meta_title;
public string $meta_description;
public array $site_checkboxlist;

// Use this function to return the settings group and its values
// In a view we can use: <h1>{{ settings(App\Settings\GeneralSettings::class)->site_name }}</h1>
public static function group(): string
{
return 'general';
}
}
namespace App\Settings;

use Spatie\LaravelSettings\Settings;

class GeneralSettings extends Settings
{

// Define the settings page inputs to use in the Settings Page
public string $site_name;
public string $site_email;
public string $meta_title;
public string $meta_description;
public array $site_checkboxlist;

// Use this function to return the settings group and its values
// In a view we can use: <h1>{{ settings(App\Settings\GeneralSettings::class)->site_name }}</h1>
public static function group(): string
{
return 'general';
}
}
I don’t think CollectionCast is right here either as it should just be a flat array of values.
MilenKo
MilenKo3w ago
@awcodes Well, i would expect it to work as well, however there is an error the minute I switch to array type as it tries to store a string as an array and it does not allow it. I've posted it in the initial comment that switching string to array did not do the work. Here is the error from my previous message:
Cannot assign array to property App\Settings\GeneralSettings::$site_checkboxlist of type ?string
Cannot assign array to property App\Settings\GeneralSettings::$site_checkboxlist of type ?string
I've tried also to switch the type of the checkbox as a collection, however it seems like a method like ->collection() does not exist on the form inputs... Seems like the data passed is a JSON object of type: [ '1' => 'true', '2' => 'false' ] Or some other data sorting, but this should have been considered as a string, but it is actually considered as something strange to me, as I cannot define $site_checkboxlist as array, nor as string... Maybe I should try defining it as a JSON object somehow to test, but I don't find any useful information so far about that in the casts, and i've looked into many LaravelSettings casts to figure out which one should i use and how...
awcodes
awcodes3w ago
This is working for me:
class GeneralSettings extends Settings
{
public string $site_name;
public string $site_email;
public string $meta_title;
public string $meta_description;
public array $site_checkboxlist;

public static function group(): string
{
return 'general';
}
}
class GeneralSettings extends Settings
{
public string $site_name;
public string $site_email;
public string $meta_title;
public string $meta_description;
public array $site_checkboxlist;

public static function group(): string
{
return 'general';
}
}
awcodes
awcodes3w ago
Make sure the initial payload in the DB is an empty array.
No description
No description
No description
MilenKo
MilenKo3w ago
The initial DB payload is empty, just in the DB it was '' but in your example was [] So I've switched to [] and it allowed to pass the POST, however the payload in DB and the view still remains [] and not populated with the options.... Same '' payload for other inputs worked to populate the proper choice/value, just the array was not populated as you can see on the image. Tried to correct the migration and pushed a fresh DB to test, using my migration code as:
<?php

use Spatie\LaravelSettings\Migrations\SettingsMigration;

return new class extends SettingsMigration
{
public function up(): void
{
$this->migrator->add('general.site_name', 'Default Site Name'); // text input setting
$this->migrator->add('general.site_email', '[email protected]'); // text input with email validation
$this->migrator->add('general.site_select', ''); // select dropdown input
$this->migrator->add('general.site_is_checked', ''); // checkbox input
$this->migrator->add('general.site_is_toggled', ''); // toggle input
$this->migrator->add('general.site_checkboxlist', []); // checkbox list input
$this->migrator->add('general.site_radio', ''); // radio options input
$this->migrator->add('general.meta_title', 'Default Meta Title'); // text input on another tab
$this->migrator->add('general.meta_description', 'Default Meta Description'); // demo text input for the second tab
}
};
<?php

use Spatie\LaravelSettings\Migrations\SettingsMigration;

return new class extends SettingsMigration
{
public function up(): void
{
$this->migrator->add('general.site_name', 'Default Site Name'); // text input setting
$this->migrator->add('general.site_email', '[email protected]'); // text input with email validation
$this->migrator->add('general.site_select', ''); // select dropdown input
$this->migrator->add('general.site_is_checked', ''); // checkbox input
$this->migrator->add('general.site_is_toggled', ''); // toggle input
$this->migrator->add('general.site_checkboxlist', []); // checkbox list input
$this->migrator->add('general.site_radio', ''); // radio options input
$this->migrator->add('general.meta_title', 'Default Meta Title'); // text input on another tab
$this->migrator->add('general.meta_description', 'Default Meta Description'); // demo text input for the second tab
}
};
After which I can see the payload matching yours ([]) however I am still unable to store the data in the DB and show it on...
No description
No description
No description
MilenKo
MilenKo3w ago
It saves the page correctly with the $site_checkboxlist defined as an array, however no data is stored in the DB during save and no errors shown in the log either to indicate an issue...
No description
MilenKo
MilenKo3w ago
Wholly guaccamole... It was my silly mistake of trying to define the input form field as an array, e.g.
// All CheckboxList options: https://filamentphp.com/docs/3.x/forms/fields/checkbox-list
CheckboxList::make('site_checkboxlist[]') // checkbox list with supplied options
->options([
'1' => '== A ==',
'2' => '== B ==',
'3' => '== C =='
]),
// All CheckboxList options: https://filamentphp.com/docs/3.x/forms/fields/checkbox-list
CheckboxList::make('site_checkboxlist[]') // checkbox list with supplied options
->options([
'1' => '== A ==',
'2' => '== B ==',
'3' => '== C =='
]),
Must be one of all my attempts to please the array data storing... Once I removed it, I CONFIRM YOUR CODE WORKS !!! Thank you @awcodes you saved me a few more weeks of scratching my head...
Want results from more Discord servers?
Add your server