Field Toggle
PandaPanel\Forms\Components\Toggle adalah field boolean yang dirender sebagai switch. Class ini extends PandaPanel\Forms\Components\Checkbox dan hanya mengganti FieldType, sehingga seluruh behavior Checkbox juga berlaku pada Toggle. Gunakan Toggle untuk setting yang secara alami dibaca sebagai "on/off". Gunakan Checkbox ketika konteksnya seperti "Saya setuju" atau ketika control menjadi bagian dari sekumpulan pilihan.
Form minimal
<?php
declare(strict_types=1);
namespace App\Panels\Admin\Resources\Users\Forms;
use PandaPanel\Forms\Components\Toggle;
use PandaPanel\Forms\FormSchema;
final class UserForm
{
public static function configure(FormSchema $schema): FormSchema
{
return $schema->schema([
Toggle::make('is_admin')
->label('Administrator')
->helperText('Administrators can reach the Admin panel and manage users.'),
]);
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Rule yang dihasilkan adalah nullable|boolean. Value dipersist ke column is_admin sebagai true atau false sesuai data yang diterima dan cast model yang digunakan.
Seluruh isi class
final class Toggle extends Checkbox
{
public function type(): FieldType
{
return FieldType::Toggle;
}
}2
3
4
5
6
7
Tidak ada method khusus Toggle. Seluruh behavior field berasal dari Checkbox dan Field.
Diwarisi dari Checkbox
| Member | Value | Dampak |
|---|---|---|
$default | false | Mengoverride default null dari Field, sehingga create form dimulai dalam keadaan switch off, bukan tanpa state. |
typeRules() | ['boolean'] | Rule boolean Laravel menerima true, false, 1, 0, "1", "0". |
castForForm() | (bool) $value | Column bernilai 0, "0", null, atau "" semuanya tiba di control sebagai false. |
FieldType::Toggle diserialisasi menjadi 'toggle', sedangkan FieldType::Checkbox menjadi 'checkbox'. String inilah satu-satunya perbedaan di wire dan yang menentukan Vue control mana yang digunakan.
Bentuk serialized payload
Toggle::make('is_admin')->toArray(null, 'create') menghasilkan payload dasar field tanpa tambahan key karena class tidak mendefinisikan extraArray():
| Key | Value |
|---|---|
type | 'toggle' |
name | 'is_admin' |
label | 'Is Admin', kecuali label() dipanggil |
value | false pada create; (bool) $record->is_admin pada edit |
validation | { required: false } |
boolean tidak termasuk browser validation hints karena switch tidak dapat menghasilkan tipe input lain dari UI normalnya.
Menulis ke timestamp, bukan boolean column
Penggunaan Toggle yang menarik adalah ketika tidak ada boolean column langsung. formatUsing() membentuk value saat masuk ke form, dehydrateTo() menentukan column tujuan, dan mutateUsing() membentuk value saat keluar dari form:
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Date;
use PandaPanel\Forms\Components\Toggle;
Toggle::make('verified')
->label('Email verified')
->helperText('Marks the address as verified without sending an email.')
->columnSpan(2)
->formatUsing(static fn (mixed $value, ?Model $record): bool => $record instanceof User
&& $record->email_verified_at !== null)
->dehydrateTo('email_verified_at')
->mutateUsing(static function (mixed $value, ?Model $record): mixed {
if ($value !== true) {
return null;
}
// Keep an existing timestamp rather than resetting it on every save.
return $record instanceof User && $record->email_verified_at !== null
? $record->email_verified_at
: Date::now();
});2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Tiga concern tetap terpisah dan melakukan tiga pekerjaan berbeda: nama field tetap verified, validation tetap boolean, tetapi hasil akhirnya dipersist sebagai nullable datetime ke email_verified_at. Tidak perlu membuat column palsu hanya agar nama field cocok dengan database.
Bereaksi terhadap Toggle
Toggle sangat cocok menjadi driver declarative condition karena value-nya hanya memiliki dua state.
use PandaPanel\Forms\Components\DateTimePicker;
use PandaPanel\Forms\Components\Toggle;
use PandaPanel\Forms\Enums\ConditionOperator;
use PandaPanel\Forms\FormSchema;
FormSchema::make()->schema([
Toggle::make('schedule')->label('Publish later'),
DateTimePicker::make('publish_at')
->visibleWhen('schedule', ConditionOperator::Truthy),
]);2
3
4
5
6
7
8
9
10
11
ConditionOperator::Truthy merupakan default operator, sehingga ->visibleWhen('schedule') memiliki arti yang sama. Condition dievaluasi ulang langsung di browser saat switch berubah dan tidak membuat request ke server.
live() tidak diperlukan untuk kasus seperti ini dan hanya menambah round trip tanpa manfaat. Gunakan live() ketika server benar-benar perlu membangun ulang schema, misalnya ketika perubahan Toggle memengaruhi options field lain. Lihat live fields.
Condition membandingkan value sebagai string. ConditionOperator memetakan true menjadi '1' dan false menjadi '0'. Karena itu ->visibleWhen('schedule', ConditionOperator::Equals, true) juga bekerja, dan setara dengan Equals, '1'.
Layout
ToggleField.vue dirender melalui FieldWrapper dengan mode inline, sehingga label dan helper text ditempatkan di sebelah kanan switch. Ini disengaja dan mengoverride inlineLabel(): secara visual, label switch seharusnya berada di samping switch terlepas dari layout form lainnya.
Penempatan lainnya tetap menjadi tanggung jawab container. Toggle menggunakan satu column secara default; columnSpan(2) dan columnSpanFull() bekerja seperti field lain.
Hal yang perlu diperhatikan
required()tidak memaksa switch menjadi ON. Method ini menambahkan rulerequired, dan Laravel menganggapfalsesebagai value yang hadir. Jadifalsetetap lolos. Dampak utamanya hanya menampilkan tanda required pada label. Jika switch harus benar-benar aktif, gunakan rule yang memang berarti accepted:phpToggle::make('accepted_terms')->rules(['accepted']);1acceptedmenerimatrue,1,"1","on","yes","true", dan menolak value lainnya.Default-nya
false, bukannull. Create form dibuka dengan switch off dan mengirimfalsejika user tidak pernah mengubahnya. Nullable column akan menerimafalsedaripada tetapnull, kecuali Anda mengubah behavior melaluidehydrateWhen()ataumutateUsing().Stored value adalah apa pun yang diterima rule
boolean. Request dengan"1"dapat dipersist sebagai string"1"jika model tidak memiliki cast. Gunakan cast model:protected function casts(): array { return ['is_admin' => 'boolean']; }.disabled()berarti read-only, bukan tidak ada. Switch tetap dirender dan tetap menampilkan current value, tetapi value browser tidak dipersist. Untuk menghapus field dari UI gunakanhidden()atauhiddenOn(). Lihat disabled and hidden fields.Gunakan Toggle dan Checkbox secara konsisten sesuai makna visual. Keduanya memiliki validation, hydration, dan dehydration yang identik. Mengganti satu dengan yang lain hanyalah rendering change tanpa migration. Namun mencampur keduanya untuk jenis pertanyaan yang sama membuat UI seolah perbedaannya memiliki makna domain tertentu.