[增添]添加了datasource的setting数据库以及默认值
This commit is contained in:
337
vendor/filament/forms/docs/03-fields/01-getting-started.md
vendored
Normal file
337
vendor/filament/forms/docs/03-fields/01-getting-started.md
vendored
Normal file
@@ -0,0 +1,337 @@
|
||||
---
|
||||
title: Getting started
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
Field classes can be found in the `Filament\Form\Components` namespace.
|
||||
|
||||
Fields reside within the schema of your form, alongside any [layout components](layout/getting-started).
|
||||
|
||||
Fields may be created using the static `make()` method, passing its unique name. The name of the field should correspond to a property on your Livewire component. You may use "dot notation" to bind fields to keys in arrays.
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/simple" alt="Form field" version="3.x" />
|
||||
|
||||
## Available fields
|
||||
|
||||
Filament ships with many types of field, suitable for editing different types of data:
|
||||
|
||||
- [Text input](text-input)
|
||||
- [Select](select)
|
||||
- [Checkbox](checkbox)
|
||||
- [Toggle](toggle)
|
||||
- [Checkbox list](checkbox-list)
|
||||
- [Radio](radio)
|
||||
- [Date-time picker](date-time-picker)
|
||||
- [File upload](file-upload)
|
||||
- [Rich editor](rich-editor)
|
||||
- [Markdown editor](markdown-editor)
|
||||
- [Repeater](repeater)
|
||||
- [Builder](builder)
|
||||
- [Tags input](tags-input)
|
||||
- [Textarea](textarea)
|
||||
- [Key-value](key-value)
|
||||
- [Color picker](color-picker)
|
||||
- [Toggle buttons](toggle-buttons)
|
||||
- [Hidden](hidden)
|
||||
|
||||
You may also [create your own custom fields](custom) to edit data however you wish.
|
||||
|
||||
## Setting a label
|
||||
|
||||
By default, the label of the field will be automatically determined based on its name. To override the field's label, you may use the `label()` method. Customizing the label in this way is useful if you wish to use a [translation string for localization](https://laravel.com/docs/localization#retrieving-translation-strings):
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->label(__('fields.name'))
|
||||
```
|
||||
|
||||
Optionally, you can have the label automatically translated [using Laravel's localization features](https://laravel.com/docs/localization) with the `translateLabel()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->translateLabel() // Equivalent to `label(__('Name'))`
|
||||
```
|
||||
|
||||
## Setting an ID
|
||||
|
||||
In the same way as labels, field IDs are also automatically determined based on their names. To override a field ID, use the `id()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->id('name-field')
|
||||
```
|
||||
|
||||
## Setting a default value
|
||||
|
||||
Fields may have a default value. This will be filled if the [form's `fill()` method](getting-started#default-data) is called without any arguments. To define a default value, use the `default()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->default('John')
|
||||
```
|
||||
|
||||
Note that these defaults are only used when the form is loaded without existing data. Inside [panel resources](../../panels/resources#resource-forms) this only works on Create Pages, as Edit Pages will always fill the data from the model.
|
||||
|
||||
## Adding helper text below the field
|
||||
|
||||
Sometimes, you may wish to provide extra information for the user of the form. For this purpose, you may add helper text below the field.
|
||||
|
||||
The `helperText()` method is used to add helper text:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->helperText('Your full name here, including any middle names.')
|
||||
```
|
||||
|
||||
This method accepts a plain text string, or an instance of `Illuminate\Support\HtmlString` or `Illuminate\Contracts\Support\Htmlable`. This allows you to render HTML, or even markdown, in the helper text:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Illuminate\Support\HtmlString;
|
||||
|
||||
TextInput::make('name')
|
||||
->helperText(new HtmlString('Your <strong>full name</strong> here, including any middle names.'))
|
||||
|
||||
TextInput::make('name')
|
||||
->helperText(str('Your **full name** here, including any middle names.')->inlineMarkdown()->toHtmlString())
|
||||
|
||||
TextInput::make('name')
|
||||
->helperText(view('name-helper-text'))
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/helper-text" alt="Form field with helper text" version="3.x" />
|
||||
|
||||
## Adding a hint next to the label
|
||||
|
||||
As well as [helper text](#adding-helper-text-below-the-field) below the field, you may also add a "hint" next to the label of the field. This is useful for displaying additional information about the field, such as a link to a help page.
|
||||
|
||||
The `hint()` method is used to add a hint:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('password')
|
||||
->hint('Forgotten your password? Bad luck.')
|
||||
```
|
||||
|
||||
This method accepts a plain text string, or an instance of `Illuminate\Support\HtmlString` or `Illuminate\Contracts\Support\Htmlable`. This allows you to render HTML, or even markdown, in the helper text:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Illuminate\Support\HtmlString;
|
||||
|
||||
TextInput::make('password')
|
||||
->hint(new HtmlString('<a href="/forgotten-password">Forgotten your password?</a>'))
|
||||
|
||||
TextInput::make('password')
|
||||
->hint(str('[Forgotten your password?](/forgotten-password)')->inlineMarkdown()->toHtmlString())
|
||||
|
||||
TextInput::make('password')
|
||||
->hint(view('forgotten-password-hint'))
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/hint" alt="Form field with hint" version="3.x" />
|
||||
|
||||
### Changing the text color of the hint
|
||||
|
||||
You can change the text color of the hint. By default, it's gray, but you may use `danger`, `info`, `primary`, `success` and `warning`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
|
||||
RichEditor::make('content')
|
||||
->hint('Translatable')
|
||||
->hintColor('primary')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/hint-color" alt="Form field with hint color" version="3.x" />
|
||||
|
||||
### Adding an icon aside the hint
|
||||
|
||||
Hints may also have an [icon](https://blade-ui-kit.com/blade-icons?set=1#search) rendered next to them:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
|
||||
RichEditor::make('content')
|
||||
->hint('Translatable')
|
||||
->hintIcon('heroicon-m-language')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/hint-icon" alt="Form field with hint icon" version="3.x" />
|
||||
|
||||
#### Adding a tooltip to a hint icon
|
||||
|
||||
Additionally, you can add a tooltip to display when you hover over the hint icon, using the `tooltip` parameter of `hintIcon()`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->hintIcon('heroicon-m-question-mark-circle', tooltip: 'Need some more information?')
|
||||
```
|
||||
|
||||
## Adding extra HTML attributes
|
||||
|
||||
You can pass extra HTML attributes to the field, which will be merged onto the outer DOM element. Pass an array of attributes to the `extraAttributes()` method, where the key is the attribute name and the value is the attribute value:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->extraAttributes(['title' => 'Text input'])
|
||||
```
|
||||
|
||||
Some fields use an underlying `<input>` or `<select>` DOM element, but this is often not the outer element in the field, so the `extraAttributes()` method may not work as you wish. In this case, you may use the `extraInputAttributes()` method, which will merge the attributes onto the `<input>` or `<select>` element:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('categories')
|
||||
->extraInputAttributes(['width' => 200])
|
||||
```
|
||||
|
||||
You can also pass extra HTML attributes to the field wrapper which surrounds the label, entry, and any other text:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('categories')
|
||||
->extraFieldWrapperAttributes(['class' => 'components-locked'])
|
||||
```
|
||||
|
||||
## Disabling a field
|
||||
|
||||
You may disable a field to prevent it from being edited by the user:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->disabled()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/disabled" alt="Disabled form field" version="3.x" />
|
||||
|
||||
Optionally, you may pass a boolean value to control if the field should be disabled or not:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Toggle;
|
||||
|
||||
Toggle::make('is_admin')
|
||||
->disabled(! auth()->user()->isAdmin())
|
||||
```
|
||||
|
||||
Disabling a field will prevent it from being saved. If you'd like it to be saved, but still not editable, use the `dehydrated()` method:
|
||||
|
||||
```php
|
||||
Toggle::make('is_admin')
|
||||
->disabled()
|
||||
->dehydrated()
|
||||
```
|
||||
|
||||
> If you choose to dehydrate the field, a skilled user could still edit the field's value by manipulating Livewire's JavaScript.
|
||||
|
||||
### Hiding a field
|
||||
|
||||
You may hide a field:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->hidden()
|
||||
```
|
||||
|
||||
Optionally, you may pass a boolean value to control if the field should be hidden or not:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->hidden(! auth()->user()->isAdmin())
|
||||
```
|
||||
|
||||
## Autofocusing a field when the form is loaded
|
||||
|
||||
Most fields are autofocusable. Typically, you should aim for the first significant field in your form to be autofocused for the best user experience. You can nominate a field to be autofocused using the `autofocus()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->autofocus()
|
||||
```
|
||||
|
||||
## Setting a placeholder
|
||||
|
||||
Many fields will also include a placeholder value for when it has no value. This is displayed in the UI but not saved if the field is submitted with no value. You may customize this placeholder using the `placeholder()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->placeholder('John Doe')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/placeholder" alt="Form field with placeholder" version="3.x" />
|
||||
|
||||
## Marking a field as required
|
||||
|
||||
By default, [required fields](validation#required) will show an asterisk `*` next to their label. You may want to hide the asterisk on forms where all fields are required, or where it makes sense to add a [hint](#adding-a-hint-next-to-the-label) to optional fields instead:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->required() // Adds validation to ensure the field is required
|
||||
->markAsRequired(false) // Removes the asterisk
|
||||
```
|
||||
|
||||
If your field is not `required()`, but you still wish to show an asterisk `*` you can use `markAsRequired()` too:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->markAsRequired()
|
||||
```
|
||||
|
||||
## Global settings
|
||||
|
||||
If you wish to change the default behavior of a field globally, then you can call the static `configureUsing()` method inside a service provider's `boot()` method or a middleware. Pass a closure which is able to modify the component. For example, if you wish to make all [checkboxes `inline(false)`](checkbox#positioning-the-label-above), you can do it like so:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Checkbox;
|
||||
|
||||
Checkbox::configureUsing(function (Checkbox $checkbox): void {
|
||||
$checkbox->inline(false);
|
||||
});
|
||||
```
|
||||
|
||||
Of course, you are still able to overwrite this behavior on each field individually:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Checkbox;
|
||||
|
||||
Checkbox::make('is_admin')
|
||||
->inline()
|
||||
```
|
||||
291
vendor/filament/forms/docs/03-fields/02-text-input.md
vendored
Normal file
291
vendor/filament/forms/docs/03-fields/02-text-input.md
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
---
|
||||
title: Text input
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
The text input allows you to interact with a string:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/text-input/simple" alt="Text input" version="3.x" />
|
||||
|
||||
## Setting the HTML input type
|
||||
|
||||
You may set the type of string using a set of methods. Some, such as `email()`, also provide validation:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('text')
|
||||
->email() // or
|
||||
->numeric() // or
|
||||
->integer() // or
|
||||
->password() // or
|
||||
->tel() // or
|
||||
->url()
|
||||
```
|
||||
|
||||
You may instead use the `type()` method to pass another [HTML input type](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#input_types):
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('backgroundColor')
|
||||
->type('color')
|
||||
```
|
||||
|
||||
## Setting the HTML input mode
|
||||
|
||||
You may set the [`inputmode` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#inputmode) of the input using the `inputMode()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('text')
|
||||
->numeric()
|
||||
->inputMode('decimal')
|
||||
```
|
||||
|
||||
## Setting the numeric step
|
||||
|
||||
You may set the [`step` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#step) of the input using the `step()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('number')
|
||||
->numeric()
|
||||
->step(100)
|
||||
```
|
||||
|
||||
## Autocompleting text
|
||||
|
||||
You may allow the text to be [autocompleted by the browser](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#autocomplete) using the `autocomplete()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('password')
|
||||
->password()
|
||||
->autocomplete('new-password')
|
||||
```
|
||||
|
||||
As a shortcut for `autocomplete="off"`, you may use `autocomplete(false)`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('password')
|
||||
->password()
|
||||
->autocomplete(false)
|
||||
```
|
||||
|
||||
For more complex autocomplete options, text inputs also support [datalists](#autocompleting-text-with-a-datalist).
|
||||
|
||||
### Autocompleting text with a datalist
|
||||
|
||||
You may specify [datalist](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist) options for a text input using the `datalist()` method:
|
||||
|
||||
```php
|
||||
TextInput::make('manufacturer')
|
||||
->datalist([
|
||||
'BWM',
|
||||
'Ford',
|
||||
'Mercedes-Benz',
|
||||
'Porsche',
|
||||
'Toyota',
|
||||
'Tesla',
|
||||
'Volkswagen',
|
||||
])
|
||||
```
|
||||
|
||||
Datalists provide autocomplete options to users when they use a text input. However, these are purely recommendations, and the user is still able to type any value into the input. If you're looking to strictly limit users to a set of predefined options, check out the [select field](select).
|
||||
|
||||
## Autocapitalizing text
|
||||
|
||||
You may allow the text to be [autocapitalized by the browser](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#autocapitalize) using the `autocapitalize()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->autocapitalize('words')
|
||||
```
|
||||
|
||||
## Adding affix text aside the field
|
||||
|
||||
You may place text before and after the input using the `prefix()` and `suffix()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('domain')
|
||||
->prefix('https://')
|
||||
->suffix('.com')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/text-input/affix" alt="Text input with affixes" version="3.x" />
|
||||
|
||||
### Using icons as affixes
|
||||
|
||||
You may place an [icon](https://blade-ui-kit.com/blade-icons?set=1#search) before and after the input using the `prefixIcon()` and `suffixIcon()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('domain')
|
||||
->url()
|
||||
->suffixIcon('heroicon-m-globe-alt')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/text-input/suffix-icon" alt="Text input with suffix icon" version="3.x" />
|
||||
|
||||
#### Setting the affix icon's color
|
||||
|
||||
Affix icons are gray by default, but you may set a different color using the `prefixIconColor()` and `suffixIconColor()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('domain')
|
||||
->url()
|
||||
->suffixIcon('heroicon-m-check-circle')
|
||||
->suffixIconColor('success')
|
||||
```
|
||||
|
||||
## Revealable password inputs
|
||||
|
||||
When using `password()`, you can also make the input `revealable()`, so that the user can see a plain text version of the password they're typing by clicking a button:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('password')
|
||||
->password()
|
||||
->revealable()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/text-input/revealable-password" alt="Text input with revealable password" version="3.x" />
|
||||
|
||||
## Input masking
|
||||
|
||||
Input masking is the practice of defining a format that the input value must conform to.
|
||||
|
||||
In Filament, you may use the `mask()` method to configure an [Alpine.js mask](https://alpinejs.dev/plugins/mask#x-mask):
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('birthday')
|
||||
->mask('99/99/9999')
|
||||
->placeholder('MM/DD/YYYY')
|
||||
```
|
||||
|
||||
To use a [dynamic mask](https://alpinejs.dev/plugins/mask#mask-functions), wrap the JavaScript in a `RawJs` object:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Support\RawJs;
|
||||
|
||||
TextInput::make('cardNumber')
|
||||
->mask(RawJs::make(<<<'JS'
|
||||
$input.startsWith('34') || $input.startsWith('37') ? '9999 999999 99999' : '9999 9999 9999 9999'
|
||||
JS))
|
||||
```
|
||||
|
||||
Alpine.js will send the entire masked value to the server, so you may need to strip certain characters from the state before validating the field and saving it. You can do this with the `stripCharacters()` method, passing in a character or an array of characters to remove from the masked value:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Support\RawJs;
|
||||
|
||||
TextInput::make('amount')
|
||||
->mask(RawJs::make('$money($input)'))
|
||||
->stripCharacters(',')
|
||||
->numeric()
|
||||
```
|
||||
|
||||
## Making the field read-only
|
||||
|
||||
Not to be confused with [disabling the field](getting-started#disabling-a-field), you may make the field "read-only" using the `readOnly()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->readOnly()
|
||||
```
|
||||
|
||||
There are a few differences, compared to [`disabled()`](getting-started#disabling-a-field):
|
||||
|
||||
- When using `readOnly()`, the field will still be sent to the server when the form is submitted. It can be mutated with the browser console, or via JavaScript. You can use [`dehydrated(false)`](advanced#preventing-a-field-from-being-dehydrated) to prevent this.
|
||||
- There are no styling changes, such as less opacity, when using `readOnly()`.
|
||||
- The field is still focusable when using `readOnly()`.
|
||||
|
||||
## Text input validation
|
||||
|
||||
As well as all rules listed on the [validation](../validation) page, there are additional rules that are specific to text inputs.
|
||||
|
||||
### Length validation
|
||||
|
||||
You may limit the length of the input by setting the `minLength()` and `maxLength()` methods. These methods add both frontend and backend validation:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('name')
|
||||
->minLength(2)
|
||||
->maxLength(255)
|
||||
```
|
||||
|
||||
You can also specify the exact length of the input by setting the `length()`. This method adds both frontend and backend validation:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('code')
|
||||
->length(8)
|
||||
```
|
||||
|
||||
### Size validation
|
||||
|
||||
You may validate the minimum and maximum value of a numeric input by setting the `minValue()` and `maxValue()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('number')
|
||||
->numeric()
|
||||
->minValue(1)
|
||||
->maxValue(100)
|
||||
```
|
||||
|
||||
### Phone number validation
|
||||
|
||||
When using a `tel()` field, the value will be validated using: `/^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\.\/0-9]*$/`.
|
||||
|
||||
If you wish to change that, then you can use the `telRegex()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::make('phone')
|
||||
->tel()
|
||||
->telRegex('/^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\.\/0-9]*$/')
|
||||
```
|
||||
|
||||
Alternatively, to customize the `telRegex()` across all fields, use a service provider:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
TextInput::configureUsing(function (TextInput $component): void {
|
||||
$component->telRegex('/^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\.\/0-9]*$/');
|
||||
});
|
||||
```
|
||||
637
vendor/filament/forms/docs/03-fields/03-select.md
vendored
Normal file
637
vendor/filament/forms/docs/03-fields/03-select.md
vendored
Normal file
@@ -0,0 +1,637 @@
|
||||
---
|
||||
title: Select
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
import LaracastsBanner from "@components/LaracastsBanner.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
<LaracastsBanner
|
||||
title="Select Input"
|
||||
description="Watch the Rapid Laravel Development with Filament series on Laracasts - it will teach you the basics of adding select fields to Filament forms."
|
||||
url="https://laracasts.com/series/rapid-laravel-development-with-filament/episodes/4"
|
||||
series="rapid-laravel-development"
|
||||
/>
|
||||
|
||||
The select component allows you to select from a list of predefined options:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'reviewing' => 'Reviewing',
|
||||
'published' => 'Published',
|
||||
])
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/select/simple" alt="Select" version="3.x" />
|
||||
|
||||
## Enabling the JavaScript select
|
||||
|
||||
By default, Filament uses the native HTML5 select. You may enable a more customizable JavaScript select using the `native(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'reviewing' => 'Reviewing',
|
||||
'published' => 'Published',
|
||||
])
|
||||
->native(false)
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/select/javascript" alt="JavaScript select" version="3.x" />
|
||||
|
||||
## Searching options
|
||||
|
||||
You may enable a search input to allow easier access to many options, using the `searchable()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->label('Author')
|
||||
->options(User::all()->pluck('name', 'id'))
|
||||
->searchable()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/select/searchable" alt="Searchable select" version="3.x" />
|
||||
|
||||
### Returning custom search results
|
||||
|
||||
If you have lots of options and want to populate them based on a database search or other external data source, you can use the `getSearchResultsUsing()` and `getOptionLabelUsing()` methods instead of `options()`.
|
||||
|
||||
The `getSearchResultsUsing()` method accepts a callback that returns search results in `$key => $value` format. The current user's search is available as `$search`, and you should use that to filter your results.
|
||||
|
||||
The `getOptionLabelUsing()` method accepts a callback that transforms the selected option `$value` into a label. This is used when the form is first loaded when the user has not made a search yet. Otherwise, the label used to display the currently selected option would not be available.
|
||||
|
||||
Both `getSearchResultsUsing()` and `getOptionLabelUsing()` must be used on the select if you want to provide custom search results:
|
||||
|
||||
```php
|
||||
Select::make('author_id')
|
||||
->searchable()
|
||||
->getSearchResultsUsing(fn (string $search): array => User::where('name', 'like', "%{$search}%")->limit(50)->pluck('name', 'id')->toArray())
|
||||
->getOptionLabelUsing(fn ($value): ?string => User::find($value)?->name),
|
||||
```
|
||||
|
||||
## Multi-select
|
||||
|
||||
The `multiple()` method on the `Select` component allows you to select multiple values from the list of options:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('technologies')
|
||||
->multiple()
|
||||
->options([
|
||||
'tailwind' => 'Tailwind CSS',
|
||||
'alpine' => 'Alpine.js',
|
||||
'laravel' => 'Laravel',
|
||||
'livewire' => 'Laravel Livewire',
|
||||
])
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/select/multiple" alt="Multi-select" version="3.x" />
|
||||
|
||||
These options are returned in JSON format. If you're saving them using Eloquent, you should be sure to add an `array` [cast](https://laravel.com/docs/eloquent-mutators#array-and-json-casting) to the model property:
|
||||
|
||||
```php
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class App extends Model
|
||||
{
|
||||
protected $casts = [
|
||||
'technologies' => 'array',
|
||||
];
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
If you're [returning custom search results](#returning-custom-search-results), you should define `getOptionLabelsUsing()` instead of `getOptionLabelUsing()`. `$values` will be passed into the callback instead of `$value`, and you should return a `$key => $value` array of labels and their corresponding values:
|
||||
|
||||
```php
|
||||
Select::make('technologies')
|
||||
->multiple()
|
||||
->searchable()
|
||||
->getSearchResultsUsing(fn (string $search): array => Technology::where('name', 'like', "%{$search}%")->limit(50)->pluck('name', 'id')->toArray())
|
||||
->getOptionLabelsUsing(fn (array $values): array => Technology::whereIn('id', $values)->pluck('name', 'id')->toArray()),
|
||||
```
|
||||
|
||||
## Grouping options
|
||||
|
||||
You can group options together under a label, to organize them better. To do this, you can pass an array of groups to `options()` or wherever you would normally pass an array of options. The keys of the array are used as group labels, and the values are arrays of options in that group:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('status')
|
||||
->searchable()
|
||||
->options([
|
||||
'In Process' => [
|
||||
'draft' => 'Draft',
|
||||
'reviewing' => 'Reviewing',
|
||||
],
|
||||
'Reviewed' => [
|
||||
'published' => 'Published',
|
||||
'rejected' => 'Rejected',
|
||||
],
|
||||
])
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/select/grouped" alt="Grouped select" version="3.x" />
|
||||
|
||||
## Integrating with an Eloquent relationship
|
||||
|
||||
> If you're building a form inside your Livewire component, make sure you have set up the [form's model](../adding-a-form-to-a-livewire-component#setting-a-form-model). Otherwise, Filament doesn't know which model to use to retrieve the relationship from.
|
||||
|
||||
You may employ the `relationship()` method of the `Select` to configure a `BelongsTo` relationship to automatically retrieve options from. The `titleAttribute` is the name of a column that will be used to generate a label for each option:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'name')
|
||||
```
|
||||
|
||||
The `multiple()` method may be used in combination with `relationship()` to use a `BelongsToMany` relationship. Filament will load the options from the relationship, and save them back to the relationship's pivot table when the form is submitted. If a `name` is not provided, Filament will use the field name as the relationship name:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('technologies')
|
||||
->multiple()
|
||||
->relationship(titleAttribute: 'name')
|
||||
```
|
||||
|
||||
When using `disabled()` with `multiple()` and `relationship()`, ensure that `disabled()` is called before `relationship()`. This ensures that the `dehydrated()` call from within `relationship()` is not overridden by the call from `disabled()`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('technologies')
|
||||
->multiple()
|
||||
->disabled()
|
||||
->relationship(titleAttribute: 'name')
|
||||
```
|
||||
|
||||
### Searching relationship options across multiple columns
|
||||
|
||||
By default, if the select is also searchable, Filament will return search results for the relationship based on the title column of the relationship. If you'd like to search across multiple columns, you can pass an array of columns to the `searchable()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'name')
|
||||
->searchable(['name', 'email'])
|
||||
```
|
||||
|
||||
### Preloading relationship options
|
||||
|
||||
If you'd like to populate the searchable options from the database when the page is loaded, instead of when the user searches, you can use the `preload()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'name')
|
||||
->searchable()
|
||||
->preload()
|
||||
```
|
||||
|
||||
### Excluding the current record
|
||||
|
||||
When working with recursive relationships, you will likely want to remove the current record from the set of results.
|
||||
|
||||
This can be easily be done using the `ignoreRecord` argument:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('parent_id')
|
||||
->relationship(name: 'parent', titleAttribute: 'name', ignoreRecord: true)
|
||||
```
|
||||
|
||||
### Customizing the relationship query
|
||||
|
||||
You may customize the database query that retrieves options using the third parameter of the `relationship()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(
|
||||
name: 'author',
|
||||
titleAttribute: 'name',
|
||||
modifyQueryUsing: fn (Builder $query) => $query->withTrashed(),
|
||||
)
|
||||
```
|
||||
|
||||
If you would like to access the current search query in the `modifyQueryUsing` function, you can inject `$search`.
|
||||
|
||||
### Customizing the relationship option labels
|
||||
|
||||
If you'd like to customize the label of each option, maybe to be more descriptive, or to concatenate a first and last name, you could use a virtual column in your database migration:
|
||||
|
||||
```php
|
||||
$table->string('full_name')->virtualAs('concat(first_name, \' \', last_name)');
|
||||
```
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'full_name')
|
||||
```
|
||||
|
||||
Alternatively, you can use the `getOptionLabelFromRecordUsing()` method to transform an option's Eloquent model into a label:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(
|
||||
name: 'author',
|
||||
modifyQueryUsing: fn (Builder $query) => $query->orderBy('first_name')->orderBy('last_name'),
|
||||
)
|
||||
->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->first_name} {$record->last_name}")
|
||||
->searchable(['first_name', 'last_name'])
|
||||
```
|
||||
|
||||
### Saving pivot data to the relationship
|
||||
|
||||
If you're using a `multiple()` relationship and your pivot table has additional columns, you can use the `pivotData()` method to specify the data that should be saved in them:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('primaryTechnologies')
|
||||
->relationship(name: 'technologies', titleAttribute: 'name')
|
||||
->multiple()
|
||||
->pivotData([
|
||||
'is_primary' => true,
|
||||
])
|
||||
```
|
||||
|
||||
### Creating a new option in a modal
|
||||
|
||||
You may define a custom form that can be used to create a new record and attach it to the `BelongsTo` relationship:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'name')
|
||||
->createOptionForm([
|
||||
Forms\Components\TextInput::make('name')
|
||||
->required(),
|
||||
Forms\Components\TextInput::make('email')
|
||||
->required()
|
||||
->email(),
|
||||
]),
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/select/create-option" alt="Select with create option button" version="3.x" />
|
||||
|
||||
The form opens in a modal, where the user can fill it with data. Upon form submission, the new record is selected by the field.
|
||||
|
||||
<AutoScreenshot name="forms/fields/select/create-option-modal" alt="Select with create option modal" version="3.x" />
|
||||
|
||||
#### Customizing new option creation
|
||||
|
||||
You can customize the creation process of the new option defined in the form using the `createOptionUsing()` method, which should return the primary key of the newly created record:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'name')
|
||||
->createOptionForm([
|
||||
// ...
|
||||
])
|
||||
->createOptionUsing(function (array $data): int {
|
||||
return auth()->user()->team->members()->create($data)->getKey();
|
||||
}),
|
||||
```
|
||||
|
||||
### Editing the selected option in a modal
|
||||
|
||||
You may define a custom form that can be used to edit the selected record and save it back to the `BelongsTo` relationship:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'name')
|
||||
->editOptionForm([
|
||||
Forms\Components\TextInput::make('name')
|
||||
->required(),
|
||||
Forms\Components\TextInput::make('email')
|
||||
->required()
|
||||
->email(),
|
||||
]),
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/select/edit-option" alt="Select with edit option button" version="3.x" />
|
||||
|
||||
The form opens in a modal, where the user can fill it with data. Upon form submission, the data from the form is saved back to the record.
|
||||
|
||||
<AutoScreenshot name="forms/fields/select/edit-option-modal" alt="Select with edit option modal" version="3.x" />
|
||||
|
||||
### Handling `MorphTo` relationships
|
||||
|
||||
`MorphTo` relationships are special, since they give the user the ability to select records from a range of different models. Because of this, we have a dedicated `MorphToSelect` component which is not actually a select field, rather 2 select fields inside a fieldset. The first select field allows you to select the type, and the second allows you to select the record of that type.
|
||||
|
||||
To use the `MorphToSelect`, you must pass `types()` into the component, which tell it how to render options for different types:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\MorphToSelect;
|
||||
|
||||
MorphToSelect::make('commentable')
|
||||
->types([
|
||||
MorphToSelect\Type::make(Product::class)
|
||||
->titleAttribute('name'),
|
||||
MorphToSelect\Type::make(Post::class)
|
||||
->titleAttribute('title'),
|
||||
])
|
||||
```
|
||||
|
||||
#### Customizing the option labels for each morphed type
|
||||
|
||||
The `titleAttribute()` is used to extract the titles out of each product or post. If you'd like to customize the label of each option, you can use the `getOptionLabelFromRecordUsing()` method to transform the Eloquent model into a label:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\MorphToSelect;
|
||||
|
||||
MorphToSelect::make('commentable')
|
||||
->types([
|
||||
MorphToSelect\Type::make(Product::class)
|
||||
->getOptionLabelFromRecordUsing(fn (Product $record): string => "{$record->name} - {$record->slug}"),
|
||||
MorphToSelect\Type::make(Post::class)
|
||||
->titleAttribute('title'),
|
||||
])
|
||||
```
|
||||
|
||||
#### Customizing the relationship query for each morphed type
|
||||
|
||||
You may customize the database query that retrieves options using the `modifyOptionsQueryUsing()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\MorphToSelect;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
MorphToSelect::make('commentable')
|
||||
->types([
|
||||
MorphToSelect\Type::make(Product::class)
|
||||
->titleAttribute('name')
|
||||
->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereBelongsTo($this->team)),
|
||||
MorphToSelect\Type::make(Post::class)
|
||||
->titleAttribute('title')
|
||||
->modifyOptionsQueryUsing(fn (Builder $query) => $query->whereBelongsTo($this->team)),
|
||||
])
|
||||
```
|
||||
|
||||
> Many of the same options in the select field are available for `MorphToSelect`, including `searchable()`, `preload()`, `native()`, `allowHtml()`, and `optionsLimit()`.
|
||||
|
||||
## Allowing HTML in the option labels
|
||||
|
||||
By default, Filament will escape any HTML in the option labels. If you'd like to allow HTML, you can use the `allowHtml()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('technology')
|
||||
->options([
|
||||
'tailwind' => '<span class="text-blue-500">Tailwind</span>',
|
||||
'alpine' => '<span class="text-green-500">Alpine</span>',
|
||||
'laravel' => '<span class="text-red-500">Laravel</span>',
|
||||
'livewire' => '<span class="text-pink-500">Livewire</span>',
|
||||
])
|
||||
->searchable()
|
||||
->allowHtml()
|
||||
```
|
||||
|
||||
Be aware that you will need to ensure that the HTML is safe to render, otherwise your application will be vulnerable to XSS attacks.
|
||||
|
||||
## Disable placeholder selection
|
||||
|
||||
You can prevent the placeholder (null option) from being selected using the `selectablePlaceholder()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'reviewing' => 'Reviewing',
|
||||
'published' => 'Published',
|
||||
])
|
||||
->default('draft')
|
||||
->selectablePlaceholder(false)
|
||||
```
|
||||
|
||||
## Disabling specific options
|
||||
|
||||
You can disable specific options using the `disableOptionWhen()` method. It accepts a closure, in which you can check if the option with a specific `$value` should be disabled:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'reviewing' => 'Reviewing',
|
||||
'published' => 'Published',
|
||||
])
|
||||
->default('draft')
|
||||
->disableOptionWhen(fn (string $value): bool => $value === 'published')
|
||||
```
|
||||
|
||||
If you want to retrieve the options that have not been disabled, e.g. for validation purposes, you can do so using `getEnabledOptions()`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'reviewing' => 'Reviewing',
|
||||
'published' => 'Published',
|
||||
])
|
||||
->default('draft')
|
||||
->disableOptionWhen(fn (string $value): bool => $value === 'published')
|
||||
->in(fn (Select $component): array => array_keys($component->getEnabledOptions()))
|
||||
```
|
||||
|
||||
## Adding affix text aside the field
|
||||
|
||||
You may place text before and after the input using the `prefix()` and `suffix()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('domain')
|
||||
->prefix('https://')
|
||||
->suffix('.com')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/select/affix" alt="Select with affixes" version="3.x" />
|
||||
|
||||
### Using icons as affixes
|
||||
|
||||
You may place an [icon](https://blade-ui-kit.com/blade-icons?set=1#search) before and after the input using the `prefixIcon()` and `suffixIcon()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('domain')
|
||||
->suffixIcon('heroicon-m-globe-alt')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/select/suffix-icon" alt="Select with suffix icon" version="3.x" />
|
||||
|
||||
#### Setting the affix icon's color
|
||||
|
||||
Affix icons are gray by default, but you may set a different color using the `prefixIconColor()` and `suffixIconColor()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('domain')
|
||||
->suffixIcon('heroicon-m-check-circle')
|
||||
->suffixIconColor('success')
|
||||
```
|
||||
|
||||
## Setting a custom loading message
|
||||
|
||||
When you're using a searchable select or multi-select, you may want to display a custom message while the options are loading. You can do this using the `loadingMessage()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'name')
|
||||
->searchable()
|
||||
->loadingMessage('Loading authors...')
|
||||
```
|
||||
|
||||
## Setting a custom no search results message
|
||||
|
||||
When you're using a searchable select or multi-select, you may want to display a custom message when no search results are found. You can do this using the `noSearchResultsMessage()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'name')
|
||||
->searchable()
|
||||
->noSearchResultsMessage('No authors found.')
|
||||
```
|
||||
|
||||
## Setting a custom search prompt
|
||||
|
||||
When you're using a searchable select or multi-select, you may want to display a custom message when the user has not yet entered a search term. You can do this using the `searchPrompt()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'name')
|
||||
->searchable(['name', 'email'])
|
||||
->searchPrompt('Search authors by their name or email address')
|
||||
```
|
||||
|
||||
## Setting a custom searching message
|
||||
|
||||
When you're using a searchable select or multi-select, you may want to display a custom message while the search results are being loaded. You can do this using the `searchingMessage()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'name')
|
||||
->searchable()
|
||||
->searchingMessage('Searching authors...')
|
||||
```
|
||||
|
||||
## Tweaking the search debounce
|
||||
|
||||
By default, Filament will wait 1000 milliseconds (1 second) before searching for options when the user types in a searchable select or multi-select. It will also wait 1000 milliseconds between searches, if the user is continuously typing into the search input. You can change this using the `searchDebounce()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'name')
|
||||
->searchable()
|
||||
->searchDebounce(500)
|
||||
```
|
||||
|
||||
Ensure that you are not lowering the debounce too much, as this may cause the select to become slow and unresponsive due to a high number of network requests to retrieve options from server.
|
||||
|
||||
## Limiting the number of options
|
||||
|
||||
You can limit the number of options that are displayed in a searchable select or multi-select using the `optionsLimit()` method. The default is 50:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'name')
|
||||
->searchable()
|
||||
->optionsLimit(20)
|
||||
```
|
||||
|
||||
Ensure that you are not raising the limit too high, as this may cause the select to become slow and unresponsive due to high in-browser memory usage.
|
||||
|
||||
## Select validation
|
||||
|
||||
As well as all rules listed on the [validation](../validation) page, there are additional rules that are specific to selects.
|
||||
|
||||
### Selected items validation
|
||||
|
||||
You can validate the minimum and maximum number of items that you can select in a [multi-select](#multi-select) by setting the `minItems()` and `maxItems()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('technologies')
|
||||
->multiple()
|
||||
->options([
|
||||
'tailwind' => 'Tailwind CSS',
|
||||
'alpine' => 'Alpine.js',
|
||||
'laravel' => 'Laravel',
|
||||
'livewire' => 'Laravel Livewire',
|
||||
])
|
||||
->minItems(1)
|
||||
->maxItems(3)
|
||||
```
|
||||
|
||||
## Customizing the select action objects
|
||||
|
||||
This field uses action objects for easy customization of buttons within it. You can customize these buttons by passing a function to an action registration method. The function has access to the `$action` object, which you can use to [customize it](../../actions/trigger-button) or [customize its modal](../../actions/modals). The following methods are available to customize the actions:
|
||||
|
||||
- `createOptionAction()`
|
||||
- `editOptionAction()`
|
||||
- `manageOptionActions()` (for customizing both the create and edit option actions at once)
|
||||
|
||||
Here is an example of how you might customize an action:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Actions\Action;
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Select::make('author_id')
|
||||
->relationship(name: 'author', titleAttribute: 'name')
|
||||
->createOptionAction(
|
||||
fn (Action $action) => $action->modalWidth('3xl'),
|
||||
)
|
||||
```
|
||||
81
vendor/filament/forms/docs/03-fields/04-checkbox.md
vendored
Normal file
81
vendor/filament/forms/docs/03-fields/04-checkbox.md
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
---
|
||||
title: Checkbox
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
The checkbox component, similar to a [toggle](toggle), allows you to interact a boolean value.
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Checkbox;
|
||||
|
||||
Checkbox::make('is_admin')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/checkbox/simple" alt="Checkbox" version="3.x" />
|
||||
|
||||
If you're saving the boolean value using Eloquent, you should be sure to add a `boolean` [cast](https://laravel.com/docs/eloquent-mutators#attribute-casting) to the model property:
|
||||
|
||||
```php
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
protected $casts = [
|
||||
'is_admin' => 'boolean',
|
||||
];
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Positioning the label above
|
||||
|
||||
Checkbox fields have two layout modes, inline and stacked. By default, they are inline.
|
||||
|
||||
When the checkbox is inline, its label is adjacent to it:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Checkbox;
|
||||
|
||||
Checkbox::make('is_admin')->inline()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/checkbox/inline" alt="Checkbox with its label inline" version="3.x" />
|
||||
|
||||
When the checkbox is stacked, its label is above it:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Checkbox;
|
||||
|
||||
Checkbox::make('is_admin')->inline(false)
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/checkbox/not-inline" alt="Checkbox with its label above" version="3.x" />
|
||||
|
||||
## Checkbox validation
|
||||
|
||||
As well as all rules listed on the [validation](../validation) page, there are additional rules that are specific to checkboxes.
|
||||
|
||||
### Accepted validation
|
||||
|
||||
You may ensure that the checkbox is checked using the `accepted()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Checkbox;
|
||||
|
||||
Checkbox::make('terms_of_service')
|
||||
->accepted()
|
||||
```
|
||||
|
||||
### Declined validation
|
||||
|
||||
You may ensure that the checkbox is not checked using the `declined()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Checkbox;
|
||||
|
||||
Checkbox::make('is_under_18')
|
||||
->declined()
|
||||
```
|
||||
113
vendor/filament/forms/docs/03-fields/05-toggle.md
vendored
Normal file
113
vendor/filament/forms/docs/03-fields/05-toggle.md
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
---
|
||||
title: Toggle
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
The toggle component, similar to a [checkbox](checkbox), allows you to interact a boolean value.
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Toggle;
|
||||
|
||||
Toggle::make('is_admin')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle/simple" alt="Toggle" version="3.x" />
|
||||
|
||||
If you're saving the boolean value using Eloquent, you should be sure to add a `boolean` [cast](https://laravel.com/docs/eloquent-mutators#attribute-casting) to the model property:
|
||||
|
||||
```php
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
protected $casts = [
|
||||
'is_admin' => 'boolean',
|
||||
];
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Adding icons to the toggle button
|
||||
|
||||
Toggles may also use an [icon](https://blade-ui-kit.com/blade-icons?set=1#search) to represent the "on" and "off" state of the button. To add an icon to the "on" state, use the `onIcon()` method. To add an icon to the "off" state, use the `offIcon()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Toggle;
|
||||
|
||||
Toggle::make('is_admin')
|
||||
->onIcon('heroicon-m-bolt')
|
||||
->offIcon('heroicon-m-user')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle/icons" alt="Toggle icons" version="3.x" />
|
||||
|
||||
## Customizing the color of the toggle button
|
||||
|
||||
You may also customize the color representing the "on" or "off" state of the toggle. These may be either `danger`, `gray`, `info`, `primary`, `success` or `warning`. To add a color to the "on" state, use the `onColor()` method. To add a color to the "off" state, use the `offColor()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Toggle;
|
||||
|
||||
Toggle::make('is_admin')
|
||||
->onColor('success')
|
||||
->offColor('danger')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle/off-color" alt="Toggle off color" version="3.x" />
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle/on-color" alt="Toggle on color" version="3.x" />
|
||||
|
||||
## Positioning the label above
|
||||
|
||||
Toggle fields have two layout modes, inline and stacked. By default, they are inline.
|
||||
|
||||
When the toggle is inline, its label is adjacent to it:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Toggle;
|
||||
|
||||
Toggle::make('is_admin')
|
||||
->inline()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle/inline" alt="Toggle with its label inline" version="3.x" />
|
||||
|
||||
When the toggle is stacked, its label is above it:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Toggle;
|
||||
|
||||
Toggle::make('is_admin')
|
||||
->inline(false)
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle/not-inline" alt="Toggle with its label above" version="3.x" />
|
||||
|
||||
## Toggle validation
|
||||
|
||||
As well as all rules listed on the [validation](../validation) page, there are additional rules that are specific to toggles.
|
||||
|
||||
### Accepted validation
|
||||
|
||||
You may ensure that the toggle is "on" using the `accepted()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Toggle;
|
||||
|
||||
Toggle::make('terms_of_service')
|
||||
->accepted()
|
||||
```
|
||||
|
||||
### Declined validation
|
||||
|
||||
You may ensure that the toggle is "off" using the `declined()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Toggle;
|
||||
|
||||
Toggle::make('is_under_18')
|
||||
->declined()
|
||||
```
|
||||
322
vendor/filament/forms/docs/03-fields/06-checkbox-list.md
vendored
Normal file
322
vendor/filament/forms/docs/03-fields/06-checkbox-list.md
vendored
Normal file
@@ -0,0 +1,322 @@
|
||||
---
|
||||
title: Checkbox list
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
import LaracastsBanner from "@components/LaracastsBanner.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
<LaracastsBanner
|
||||
title="Checkbox List"
|
||||
description="Watch the Rapid Laravel Development with Filament series on Laracasts - it will teach you the basics of adding checkbox list fields to Filament forms."
|
||||
url="https://laracasts.com/series/rapid-laravel-development-with-filament/episodes/5"
|
||||
series="rapid-laravel-development"
|
||||
/>
|
||||
|
||||
|
||||
The checkbox list component allows you to select multiple values from a list of predefined options:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->options([
|
||||
'tailwind' => 'Tailwind CSS',
|
||||
'alpine' => 'Alpine.js',
|
||||
'laravel' => 'Laravel',
|
||||
'livewire' => 'Laravel Livewire',
|
||||
])
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/checkbox-list/simple" alt="Checkbox list" version="3.x" />
|
||||
|
||||
These options are returned in JSON format. If you're saving them using Eloquent, you should be sure to add an `array` [cast](https://laravel.com/docs/eloquent-mutators#array-and-json-casting) to the model property:
|
||||
|
||||
```php
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class App extends Model
|
||||
{
|
||||
protected $casts = [
|
||||
'technologies' => 'array',
|
||||
];
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Setting option descriptions
|
||||
|
||||
You can optionally provide descriptions to each option using the `descriptions()` method. This method accepts an array of plain text strings, or instances of `Illuminate\Support\HtmlString` or `Illuminate\Contracts\Support\Htmlable`. This allows you to render HTML, or even markdown, in the descriptions:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
use Illuminate\Support\HtmlString;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->options([
|
||||
'tailwind' => 'Tailwind CSS',
|
||||
'alpine' => 'Alpine.js',
|
||||
'laravel' => 'Laravel',
|
||||
'livewire' => 'Laravel Livewire',
|
||||
])
|
||||
->descriptions([
|
||||
'tailwind' => 'A utility-first CSS framework for rapidly building modern websites without ever leaving your HTML.',
|
||||
'alpine' => new HtmlString('A rugged, minimal tool for composing behavior <strong>directly in your markup</strong>.'),
|
||||
'laravel' => str('A **web application** framework with expressive, elegant syntax.')->inlineMarkdown()->toHtmlString(),
|
||||
'livewire' => 'A full-stack framework for Laravel building dynamic interfaces simple, without leaving the comfort of Laravel.',
|
||||
])
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/checkbox-list/option-descriptions" alt="Checkbox list with option descriptions" version="3.x" />
|
||||
|
||||
Be sure to use the same `key` in the descriptions array as the `key` in the option array so the right description matches the right option.
|
||||
|
||||
## Splitting options into columns
|
||||
|
||||
You may split options into columns by using the `columns()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->options([
|
||||
// ...
|
||||
])
|
||||
->columns(2)
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/checkbox-list/columns" alt="Checkbox list with 2 columns" version="3.x" />
|
||||
|
||||
This method accepts the same options as the `columns()` method of the [grid](layout/grid). This allows you to responsively customize the number of columns at various breakpoints.
|
||||
|
||||
### Setting the grid direction
|
||||
|
||||
By default, when you arrange checkboxes into columns, they will be listed in order vertically. If you'd like to list them horizontally, you may use the `gridDirection('row')` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->options([
|
||||
// ...
|
||||
])
|
||||
->columns(2)
|
||||
->gridDirection('row')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/checkbox-list/rows" alt="Checkbox list with 2 rows" version="3.x" />
|
||||
|
||||
## Disabling specific options
|
||||
|
||||
You can disable specific options using the `disableOptionWhen()` method. It accepts a closure, in which you can check if the option with a specific `$value` should be disabled:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->options([
|
||||
'tailwind' => 'Tailwind CSS',
|
||||
'alpine' => 'Alpine.js',
|
||||
'laravel' => 'Laravel',
|
||||
'livewire' => 'Laravel Livewire',
|
||||
])
|
||||
->disableOptionWhen(fn (string $value): bool => $value === 'livewire')
|
||||
```
|
||||
|
||||
If you want to retrieve the options that have not been disabled, e.g. for validation purposes, you can do so using `getEnabledOptions()`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->options([
|
||||
'tailwind' => 'Tailwind CSS',
|
||||
'alpine' => 'Alpine.js',
|
||||
'laravel' => 'Laravel',
|
||||
'livewire' => 'Laravel Livewire',
|
||||
'heroicons' => 'SVG icons',
|
||||
])
|
||||
->disableOptionWhen(fn (string $value): bool => $value === 'heroicons')
|
||||
->in(fn (CheckboxList $component): array => array_keys($component->getEnabledOptions()))
|
||||
```
|
||||
|
||||
## Searching options
|
||||
|
||||
You may enable a search input to allow easier access to many options, using the `searchable()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->options([
|
||||
// ...
|
||||
])
|
||||
->searchable()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/checkbox-list/searchable" alt="Searchable checkbox list" version="3.x" />
|
||||
|
||||
## Bulk toggling checkboxes
|
||||
|
||||
You may allow users to toggle all checkboxes at once using the `bulkToggleable()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->options([
|
||||
// ...
|
||||
])
|
||||
->bulkToggleable()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/checkbox-list/bulk-toggleable" alt="Bulk toggleable checkbox list" version="3.x" />
|
||||
|
||||
## Integrating with an Eloquent relationship
|
||||
|
||||
> If you're building a form inside your Livewire component, make sure you have set up the [form's model](../adding-a-form-to-a-livewire-component#setting-a-form-model). Otherwise, Filament doesn't know which model to use to retrieve the relationship from.
|
||||
|
||||
You may employ the `relationship()` method of the `CheckboxList` to point to a `BelongsToMany` relationship. Filament will load the options from the relationship, and save them back to the relationship's pivot table when the form is submitted. The `titleAttribute` is the name of a column that will be used to generate a label for each option:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->relationship(titleAttribute: 'name')
|
||||
```
|
||||
|
||||
When using `disabled()` with `relationship()`, ensure that `disabled()` is called before `relationship()`. This ensures that the `dehydrated()` call from within `relationship()` is not overridden by the call from `disabled()`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->disabled()
|
||||
->relationship(titleAttribute: 'name')
|
||||
```
|
||||
|
||||
### Customizing the relationship query
|
||||
|
||||
You may customize the database query that retrieves options using the `modifyOptionsQueryUsing` parameter of the `relationship()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->relationship(
|
||||
titleAttribute: 'name',
|
||||
modifyQueryUsing: fn (Builder $query) => $query->withTrashed(),
|
||||
)
|
||||
```
|
||||
|
||||
### Customizing the relationship option labels
|
||||
|
||||
If you'd like to customize the label of each option, maybe to be more descriptive, or to concatenate a first and last name, you could use a virtual column in your database migration:
|
||||
|
||||
```php
|
||||
$table->string('full_name')->virtualAs('concat(first_name, \' \', last_name)');
|
||||
```
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('authors')
|
||||
->relationship(titleAttribute: 'full_name')
|
||||
```
|
||||
|
||||
Alternatively, you can use the `getOptionLabelFromRecordUsing()` method to transform an option's Eloquent model into a label:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
CheckboxList::make('authors')
|
||||
->relationship(
|
||||
modifyQueryUsing: fn (Builder $query) => $query->orderBy('first_name')->orderBy('last_name'),
|
||||
)
|
||||
->getOptionLabelFromRecordUsing(fn (Model $record) => "{$record->first_name} {$record->last_name}")
|
||||
```
|
||||
|
||||
### Saving pivot data to the relationship
|
||||
|
||||
If your pivot table has additional columns, you can use the `pivotData()` method to specify the data that should be saved in them:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('primaryTechnologies')
|
||||
->relationship(name: 'technologies', titleAttribute: 'name')
|
||||
->pivotData([
|
||||
'is_primary' => true,
|
||||
])
|
||||
```
|
||||
|
||||
## Setting a custom no search results message
|
||||
|
||||
When you're using a searchable checkbox list, you may want to display a custom message when no search results are found. You can do this using the `noSearchResultsMessage()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->options([
|
||||
// ...
|
||||
])
|
||||
->searchable()
|
||||
->noSearchResultsMessage('No technologies found.')
|
||||
```
|
||||
|
||||
## Setting a custom search prompt
|
||||
|
||||
When you're using a searchable checkbox list, you may want to tweak the search input's placeholder when the user has not yet entered a search term. You can do this using the `searchPrompt()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->options([
|
||||
// ...
|
||||
])
|
||||
->searchable()
|
||||
->searchPrompt('Search for a technology')
|
||||
```
|
||||
|
||||
## Tweaking the search debounce
|
||||
|
||||
By default, Filament will wait 1000 milliseconds (1 second) before searching for options when the user types in a searchable checkbox list. It will also wait 1000 milliseconds between searches if the user is continuously typing into the search input. You can change this using the `searchDebounce()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->options([
|
||||
// ...
|
||||
])
|
||||
->searchable()
|
||||
->searchDebounce(500)
|
||||
```
|
||||
|
||||
## Customizing the checkbox list action objects
|
||||
|
||||
This field uses action objects for easy customization of buttons within it. You can customize these buttons by passing a function to an action registration method. The function has access to the `$action` object, which you can use to [customize it](../../actions/trigger-button). The following methods are available to customize the actions:
|
||||
|
||||
- `selectAllAction()`
|
||||
- `deselectAllAction()`
|
||||
|
||||
Here is an example of how you might customize an action:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Actions\Action;
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
|
||||
CheckboxList::make('technologies')
|
||||
->options([
|
||||
// ...
|
||||
])
|
||||
->selectAllAction(
|
||||
fn (Action $action) => $action->label('Select all technologies'),
|
||||
)
|
||||
```
|
||||
117
vendor/filament/forms/docs/03-fields/07-radio.md
vendored
Normal file
117
vendor/filament/forms/docs/03-fields/07-radio.md
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
---
|
||||
title: Radio
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
The radio input provides a radio button group for selecting a single value from a list of predefined options:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Radio;
|
||||
|
||||
Radio::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'scheduled' => 'Scheduled',
|
||||
'published' => 'Published'
|
||||
])
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/radio/simple" alt="Radio" version="3.x" />
|
||||
|
||||
## Setting option descriptions
|
||||
|
||||
You can optionally provide descriptions to each option using the `descriptions()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Radio;
|
||||
|
||||
Radio::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'scheduled' => 'Scheduled',
|
||||
'published' => 'Published'
|
||||
])
|
||||
->descriptions([
|
||||
'draft' => 'Is not visible.',
|
||||
'scheduled' => 'Will be visible.',
|
||||
'published' => 'Is visible.'
|
||||
])
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/radio/option-descriptions" alt="Radio with option descriptions" version="3.x" />
|
||||
|
||||
Be sure to use the same `key` in the descriptions array as the `key` in the option array so the right description matches the right option.
|
||||
|
||||
## Boolean options
|
||||
|
||||
If you want a simple boolean radio button group, with "Yes" and "No" options, you can use the `boolean()` method:
|
||||
|
||||
```php
|
||||
Radio::make('feedback')
|
||||
->label('Like this post?')
|
||||
->boolean()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/radio/boolean" alt="Boolean radio" version="3.x" />
|
||||
|
||||
## Positioning the options inline with the label
|
||||
|
||||
You may wish to display the options `inline()` with the label instead of below it:
|
||||
|
||||
```php
|
||||
Radio::make('feedback')
|
||||
->label('Like this post?')
|
||||
->boolean()
|
||||
->inline()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/radio/inline" alt="Inline radio" version="3.x" />
|
||||
|
||||
## Positioning the options inline with each other but below the label
|
||||
|
||||
You may wish to display the options `inline()` with each other but below the label:
|
||||
|
||||
```php
|
||||
Radio::make('feedback')
|
||||
->label('Like this post?')
|
||||
->boolean()
|
||||
->inline()
|
||||
->inlineLabel(false)
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/radio/inline-under-label" alt="Inline radio under label" version="3.x" />
|
||||
|
||||
## Disabling specific options
|
||||
|
||||
You can disable specific options using the `disableOptionWhen()` method. It accepts a closure, in which you can check if the option with a specific `$value` should be disabled:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Radio;
|
||||
|
||||
Radio::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'scheduled' => 'Scheduled',
|
||||
'published' => 'Published',
|
||||
])
|
||||
->disableOptionWhen(fn (string $value): bool => $value === 'published')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/radio/disabled-option" alt="Radio with disabled option" version="3.x" />
|
||||
|
||||
If you want to retrieve the options that have not been disabled, e.g. for validation purposes, you can do so using `getEnabledOptions()`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Radio;
|
||||
|
||||
Radio::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'scheduled' => 'Scheduled',
|
||||
'published' => 'Published',
|
||||
])
|
||||
->disableOptionWhen(fn (string $value): bool => $value === 'published')
|
||||
->in(fn (Radio $component): array => array_keys($component->getEnabledOptions()))
|
||||
```
|
||||
261
vendor/filament/forms/docs/03-fields/08-date-time-picker.md
vendored
Normal file
261
vendor/filament/forms/docs/03-fields/08-date-time-picker.md
vendored
Normal file
@@ -0,0 +1,261 @@
|
||||
---
|
||||
title: Date-time picker
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
The date-time picker provides an interactive interface for selecting a date and/or a time.
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\DateTimePicker;
|
||||
use Filament\Forms\Components\TimePicker;
|
||||
|
||||
DateTimePicker::make('published_at')
|
||||
DatePicker::make('date_of_birth')
|
||||
TimePicker::make('alarm_at')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/date-time-picker/simple" alt="Date time pickers" version="3.x" />
|
||||
|
||||
## Customizing the storage format
|
||||
|
||||
You may customize the format of the field when it is saved in your database, using the `format()` method. This accepts a string date format, using [PHP date formatting tokens](https://www.php.net/manual/en/datetime.format.php):
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
|
||||
DatePicker::make('date_of_birth')
|
||||
->format('d/m/Y')
|
||||
```
|
||||
|
||||
## Disabling the seconds input
|
||||
|
||||
When using the time picker, you may disable the seconds input using the `seconds(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DateTimePicker;
|
||||
|
||||
DateTimePicker::make('published_at')
|
||||
->seconds(false)
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/date-time-picker/without-seconds" alt="Date time picker without seconds" version="3.x" />
|
||||
|
||||
## Timezones
|
||||
|
||||
If you'd like users to be able to manage dates in their own timezone, you can use the `timezone()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DateTimePicker;
|
||||
|
||||
DateTimePicker::make('published_at')
|
||||
->timezone('America/New_York')
|
||||
```
|
||||
|
||||
While dates will still be stored using the app's configured timezone, the date will now load in the new timezone, and it will be converted back when the form is saved.
|
||||
|
||||
## Enabling the JavaScript date picker
|
||||
|
||||
By default, Filament uses the native HTML5 date picker. You may enable a more customizable JavaScript date picker using the `native(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
|
||||
DatePicker::make('date_of_birth')
|
||||
->native(false)
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/date-time-picker/javascript" alt="JavaScript-based date time picker" version="3.x" />
|
||||
|
||||
Please be aware that while being accessible, the JavaScript date picker does not support full keyboard input in the same way that the native date picker does. If you require full keyboard input, you should use the native date picker.
|
||||
|
||||
### Customizing the display format
|
||||
|
||||
You may customize the display format of the field, separately from the format used when it is saved in your database. For this, use the `displayFormat()` method, which also accepts a string date format, using [PHP date formatting tokens](https://www.php.net/manual/en/datetime.format.php):
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
|
||||
DatePicker::make('date_of_birth')
|
||||
->native(false)
|
||||
->displayFormat('d/m/Y')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/date-time-picker/display-format" alt="Date time picker with custom display format" version="3.x" />
|
||||
|
||||
You may also configure the locale that is used when rendering the display, if you want to use different locale from your app config. For this, you can use the `locale()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
|
||||
DatePicker::make('date_of_birth')
|
||||
->native(false)
|
||||
->displayFormat('d F Y')
|
||||
->locale('fr')
|
||||
```
|
||||
|
||||
### Configuring the time input intervals
|
||||
|
||||
You may customize the input interval for increasing/decreasing the hours/minutes /seconds using the `hoursStep()` , `minutesStep()` or `secondsStep()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DateTimePicker;
|
||||
|
||||
DateTimePicker::make('published_at')
|
||||
->native(false)
|
||||
->hoursStep(2)
|
||||
->minutesStep(15)
|
||||
->secondsStep(10)
|
||||
```
|
||||
|
||||
### Configuring the first day of the week
|
||||
|
||||
In some countries, the first day of the week is not Monday. To customize the first day of the week in the date picker, use the `firstDayOfWeek()` method on the component. 0 to 7 are accepted values, with Monday as 1 and Sunday as 7 or 0:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DateTimePicker;
|
||||
|
||||
DateTimePicker::make('published_at')
|
||||
->native(false)
|
||||
->firstDayOfWeek(7)
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/date-time-picker/week-starts-on-sunday" alt="Date time picker where the week starts on Sunday" version="3.x" />
|
||||
|
||||
There are additionally convenient helper methods to set the first day of the week more semantically:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DateTimePicker;
|
||||
|
||||
DateTimePicker::make('published_at')
|
||||
->native(false)
|
||||
->weekStartsOnMonday()
|
||||
|
||||
DateTimePicker::make('published_at')
|
||||
->native(false)
|
||||
->weekStartsOnSunday()
|
||||
```
|
||||
|
||||
### Disabling specific dates
|
||||
|
||||
To prevent specific dates from being selected:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DateTimePicker;
|
||||
|
||||
DateTimePicker::make('date')
|
||||
->native(false)
|
||||
->disabledDates(['2000-01-03', '2000-01-15', '2000-01-20'])
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/date-time-picker/disabled-dates" alt="Date time picker where dates are disabled" version="3.x" />
|
||||
|
||||
### Closing the picker when a date is selected
|
||||
|
||||
To close the picker when a date is selected, you can use the `closeOnDateSelection()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DateTimePicker;
|
||||
|
||||
DateTimePicker::make('date')
|
||||
->native(false)
|
||||
->closeOnDateSelection()
|
||||
```
|
||||
|
||||
## Autocompleting dates with a datalist
|
||||
|
||||
Unless you're using the [JavaScript date picker](#enabling-the-javascript-date-picker), you may specify [datalist](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist) options for a date picker using the `datalist()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TimePicker;
|
||||
|
||||
TimePicker::make('appointment_at')
|
||||
->datalist([
|
||||
'09:00',
|
||||
'09:30',
|
||||
'10:00',
|
||||
'10:30',
|
||||
'11:00',
|
||||
'11:30',
|
||||
'12:00',
|
||||
])
|
||||
```
|
||||
|
||||
Datalists provide autocomplete options to users when they use the picker. However, these are purely recommendations, and the user is still able to type any value into the input. If you're looking to strictly limit users to a set of predefined options, check out the [select field](select).
|
||||
|
||||
## Adding affix text aside the field
|
||||
|
||||
You may place text before and after the input using the `prefix()` and `suffix()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
|
||||
DatePicker::make('date')
|
||||
->prefix('Starts')
|
||||
->suffix('at midnight')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/date-time-picker/affix" alt="Date time picker with affixes" version="3.x" />
|
||||
|
||||
### Using icons as affixes
|
||||
|
||||
You may place an [icon](https://blade-ui-kit.com/blade-icons?set=1#search) before and after the input using the `prefixIcon()` and `suffixIcon()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TimePicker;
|
||||
|
||||
TimePicker::make('at')
|
||||
->prefixIcon('heroicon-m-play')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/date-time-picker/prefix-icon" alt="Date time picker with prefix icon" version="3.x" />
|
||||
|
||||
#### Setting the affix icon's color
|
||||
|
||||
Affix icons are gray by default, but you may set a different color using the `prefixIconColor()` and `suffixIconColor()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TimePicker;
|
||||
|
||||
TimePicker::make('at')
|
||||
->prefixIcon('heroicon-m-check-circle')
|
||||
->prefixIconColor('success')
|
||||
```
|
||||
|
||||
## Making the field read-only
|
||||
|
||||
Not to be confused with [disabling the field](getting-started#disabling-a-field), you may make the field "read-only" using the `readonly()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
|
||||
DatePicker::make('date_of_birth')
|
||||
->readonly()
|
||||
```
|
||||
|
||||
Please note that this setting is only enforced on native date pickers. If you're using the [JavaScript date picker](#enabling-the-javascript-date-picker), you'll need to use [`disabled()`](getting-started#disabling-a-field).
|
||||
|
||||
There are a few differences, compared to [`disabled()`](getting-started#disabling-a-field):
|
||||
|
||||
- When using `readOnly()`, the field will still be sent to the server when the form is submitted. It can be mutated with the browser console, or via JavaScript. You can use [`dehydrated(false)`](advanced#preventing-a-field-from-being-dehydrated) to prevent this.
|
||||
- There are no styling changes, such as less opacity, when using `readOnly()`.
|
||||
- The field is still focusable when using `readOnly()`.
|
||||
|
||||
## Date-time picker validation
|
||||
|
||||
As well as all rules listed on the [validation](../validation) page, there are additional rules that are specific to date-time pickers.
|
||||
|
||||
### Max date / min date validation
|
||||
|
||||
You may restrict the minimum and maximum date that can be selected with the picker. The `minDate()` and `maxDate()` methods accept a `DateTime` instance (e.g. `Carbon`), or a string:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
|
||||
DatePicker::make('date_of_birth')
|
||||
->native(false)
|
||||
->minDate(now()->subYears(150))
|
||||
->maxDate(now())
|
||||
```
|
||||
460
vendor/filament/forms/docs/03-fields/09-file-upload.md
vendored
Normal file
460
vendor/filament/forms/docs/03-fields/09-file-upload.md
vendored
Normal file
@@ -0,0 +1,460 @@
|
||||
---
|
||||
title: File upload
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
import LaracastsBanner from "@components/LaracastsBanner.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
<LaracastsBanner
|
||||
title="File Uploads"
|
||||
description="Watch the Rapid Laravel Development with Filament series on Laracasts - it will teach you the basics of adding file upload fields to Filament forms."
|
||||
url="https://laracasts.com/series/rapid-laravel-development-with-filament/episodes/8"
|
||||
series="rapid-laravel-development"
|
||||
/>
|
||||
|
||||
The file upload field is based on [Filepond](https://pqina.nl/filepond).
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachment')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/file-upload/simple" alt="File upload" version="3.x" />
|
||||
|
||||
> Filament also supports [`spatie/laravel-medialibrary`](https://github.com/spatie/laravel-medialibrary). See our [plugin documentation](/plugins/filament-spatie-media-library) for more information.
|
||||
|
||||
## Configuring the storage disk and directory
|
||||
|
||||
By default, files will be uploaded publicly to your storage disk defined in the [configuration file](../installation#publishing-configuration). You can also set the `FILAMENT_FILESYSTEM_DISK` environment variable to change this.
|
||||
|
||||
> To correctly preview images and other files, FilePond requires files to be served from the same domain as the app, or the appropriate CORS headers need to be present. Ensure that the `APP_URL` environment variable is correct, or modify the [filesystem](https://laravel.com/docs/filesystem) driver to set the correct URL. If you're hosting files on a separate domain like S3, ensure that CORS headers are set up.
|
||||
|
||||
To change the disk and directory for a specific field, and the visibility of files, use the `disk()`, `directory()` and `visibility()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachment')
|
||||
->disk('s3')
|
||||
->directory('form-attachments')
|
||||
->visibility('private')
|
||||
```
|
||||
|
||||
> It is the responsibility of the developer to delete these files from the disk if they are removed, as Filament is unaware if they are depended on elsewhere. One way to do this automatically is observing a [model event](https://laravel.com/docs/eloquent#events).
|
||||
|
||||
## Uploading multiple files
|
||||
|
||||
You may also upload multiple files. This stores URLs in JSON:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachments')
|
||||
->multiple()
|
||||
```
|
||||
|
||||
If you're saving the file URLs using Eloquent, you should be sure to add an `array` [cast](https://laravel.com/docs/eloquent-mutators#array-and-json-casting) to the model property:
|
||||
|
||||
```php
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Message extends Model
|
||||
{
|
||||
protected $casts = [
|
||||
'attachments' => 'array',
|
||||
];
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Controlling file names
|
||||
|
||||
By default, a random file name will be generated for newly-uploaded files. This is to ensure that there are never any conflicts with existing files.
|
||||
|
||||
### Security implications of controlling file names
|
||||
|
||||
Before using the `preserveFilenames()` or `getUploadedFileNameForStorageUsing()` methods, please be aware of the security implications. If you allow users to upload files with their own file names, there are ways that they can exploit this to upload malicious files. **This applies even if you use the [`acceptedFileTypes()`](#file-type-validation) method** to restrict the types of files that can be uploaded, since it uses Laravel's `mimetypes` rule which does not validate the extension of the file, only its mime type, which could be manipulated.
|
||||
|
||||
This is specifically an issue with the `getClientOriginalName()` method on the `TemporaryUploadedFile` object, which the `preserveFilenames()` method uses. By default, Livewire generates a random file name for each file uploaded, and uses the mime type of the file to determine the file extension.
|
||||
|
||||
Using these methods **with the `local` or `public` filesystem disks** will make your app vulnerable to remote code execution if the attacker uploads a PHP file with a deceptive mime type. **Using an S3 disk protects you from this specific attack vector**, as S3 will not execute PHP files in the same way that your server might when serving files from local storage.
|
||||
|
||||
If you are using the `local` or `public` disk, you should consider using the [`storeFileNamesIn()` method](#storing-original-file-names-independently) to store the original file names in a separate column in your database, and keep the randomly generated file names in the file system. This way, you can still display the original file names to users, while keeping the file system secure.
|
||||
|
||||
On top of this security issue, you should also be aware that allowing users to upload files with their own file names can lead to conflicts with existing files, and can make it difficult to manage your storage. Users could upload files with the same name and overwrite the other's content if you do not scope them to a specific directory, so these features should in all cases only be accessible to trusted users.
|
||||
|
||||
### Preserving original file names
|
||||
|
||||
> Important: Before using this feature, please ensure that you have read the [security implications](#security-implications-of-controlling-file-names).
|
||||
|
||||
To preserve the original filenames of the uploaded files, use the `preserveFilenames()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachment')
|
||||
->preserveFilenames()
|
||||
```
|
||||
|
||||
### Generating custom file names
|
||||
|
||||
> Important: Before using this feature, please ensure that you have read the [security implications](#security-implications-of-controlling-file-names).
|
||||
|
||||
You may completely customize how file names are generated using the `getUploadedFileNameForStorageUsing()` method, and returning a string from the closure based on the `$file` that was uploaded:
|
||||
|
||||
```php
|
||||
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
|
||||
|
||||
FileUpload::make('attachment')
|
||||
->getUploadedFileNameForStorageUsing(
|
||||
fn (TemporaryUploadedFile $file): string => (string) str($file->getClientOriginalName())
|
||||
->prepend('custom-prefix-'),
|
||||
)
|
||||
```
|
||||
|
||||
### Storing original file names independently
|
||||
|
||||
You can keep the randomly generated file names, while still storing the original file name, using the `storeFileNamesIn()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachments')
|
||||
->multiple()
|
||||
->storeFileNamesIn('attachment_file_names')
|
||||
```
|
||||
|
||||
`attachment_file_names` will now store the original file names of your uploaded files, so you can save them to the database when the form is submitted. If you're uploading `multiple()` files, make sure that you add an `array` [cast](https://laravel.com/docs/eloquent-mutators#array-and-json-casting) to this Eloquent model property too.
|
||||
|
||||
## Avatar mode
|
||||
|
||||
You can enable avatar mode for your file upload field using the `avatar()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('avatar')
|
||||
->avatar()
|
||||
```
|
||||
|
||||
This will only allow images to be uploaded, and when they are, it will display them in a compact circle layout that is perfect for avatars.
|
||||
|
||||
This feature pairs well with the [circle cropper](#allowing-users-to-crop-images-as-a-circle).
|
||||
|
||||
## Image editor
|
||||
|
||||
You can enable an image editor for your file upload field using the `imageEditor()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('image')
|
||||
->image()
|
||||
->imageEditor()
|
||||
```
|
||||
|
||||
You can open the editor once you upload an image by clicking the pencil icon. You can also open the editor by clicking the pencil icon on an existing image, which will remove and re-upload it on save.
|
||||
|
||||
### Allowing users to crop images to aspect ratios
|
||||
|
||||
You can allow users to crop images to a set of specific aspect ratios using the `imageEditorAspectRatios()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('image')
|
||||
->image()
|
||||
->imageEditor()
|
||||
->imageEditorAspectRatios([
|
||||
'16:9',
|
||||
'4:3',
|
||||
'1:1',
|
||||
])
|
||||
```
|
||||
|
||||
You can also allow users to choose no aspect ratio, "free cropping", by passing `null` as an option:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('image')
|
||||
->image()
|
||||
->imageEditor()
|
||||
->imageEditorAspectRatios([
|
||||
null,
|
||||
'16:9',
|
||||
'4:3',
|
||||
'1:1',
|
||||
])
|
||||
```
|
||||
|
||||
### Setting the image editor's mode
|
||||
|
||||
You can change the mode of the image editor using the `imageEditorMode()` method, which accepts either `1`, `2` or `3`. These options are explained in the [Cropper.js documentation](https://github.com/fengyuanchen/cropperjs#viewmode):
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('image')
|
||||
->image()
|
||||
->imageEditor()
|
||||
->imageEditorMode(2)
|
||||
```
|
||||
|
||||
### Customizing the image editor's empty fill color
|
||||
|
||||
By default, the image editor will make the empty space around the image transparent. You can customize this using the `imageEditorEmptyFillColor()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('image')
|
||||
->image()
|
||||
->imageEditor()
|
||||
->imageEditorEmptyFillColor('#000000')
|
||||
```
|
||||
|
||||
### Setting the image editor's viewport size
|
||||
|
||||
You can change the size of the image editor's viewport using the `imageEditorViewportWidth()` and `imageEditorViewportHeight()` methods, which generate an aspect ratio to use across device sizes:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('image')
|
||||
->image()
|
||||
->imageEditor()
|
||||
->imageEditorViewportWidth('1920')
|
||||
->imageEditorViewportHeight('1080')
|
||||
```
|
||||
|
||||
### Allowing users to crop images as a circle
|
||||
|
||||
You can allow users to crop images as a circle using the `circleCropper()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('image')
|
||||
->image()
|
||||
->avatar()
|
||||
->imageEditor()
|
||||
->circleCropper()
|
||||
```
|
||||
|
||||
This is perfectly accompanied by the [`avatar()` method](#avatar-mode), which renders the images in a compact circle layout.
|
||||
|
||||
### Cropping and resizing images without the editor
|
||||
|
||||
Filepond allows you to crop and resize images before they are uploaded, without the need for a separate editor. You can customize this behavior using the `imageCropAspectRatio()`, `imageResizeTargetHeight()` and `imageResizeTargetWidth()` methods. `imageResizeMode()` should be set for these methods to have an effect - either [`force`, `cover`, or `contain`](https://pqina.nl/filepond/docs/api/plugins/image-resize).
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('image')
|
||||
->image()
|
||||
->imageResizeMode('cover')
|
||||
->imageCropAspectRatio('16:9')
|
||||
->imageResizeTargetWidth('1920')
|
||||
->imageResizeTargetHeight('1080')
|
||||
```
|
||||
|
||||
## Altering the appearance of the file upload area
|
||||
|
||||
You may also alter the general appearance of the Filepond component. Available options for these methods are available on the [Filepond website](https://pqina.nl/filepond/docs/api/instance/properties/#styles).
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachment')
|
||||
->imagePreviewHeight('250')
|
||||
->loadingIndicatorPosition('left')
|
||||
->panelAspectRatio('2:1')
|
||||
->panelLayout('integrated')
|
||||
->removeUploadedFileButtonPosition('right')
|
||||
->uploadButtonPosition('left')
|
||||
->uploadProgressIndicatorPosition('left')
|
||||
```
|
||||
|
||||
## Reordering files
|
||||
|
||||
You can also allow users to re-order uploaded files using the `reorderable()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachments')
|
||||
->multiple()
|
||||
->reorderable()
|
||||
```
|
||||
|
||||
When using this method, FilePond may add newly-uploaded files to the beginning of the list, instead of the end. To fix this, use the `appendFiles()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachments')
|
||||
->multiple()
|
||||
->reorderable()
|
||||
->appendFiles()
|
||||
```
|
||||
|
||||
## Opening files in a new tab
|
||||
|
||||
You can add a button to open each file in a new tab with the `openable()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachments')
|
||||
->multiple()
|
||||
->openable()
|
||||
```
|
||||
|
||||
## Downloading files
|
||||
|
||||
If you wish to add a download button to each file instead, you can use the `downloadable()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachments')
|
||||
->multiple()
|
||||
->downloadable()
|
||||
```
|
||||
|
||||
## Previewing files
|
||||
|
||||
By default, some file types can be previewed in FilePond. If you wish to disable the preview for all files, you can use the `previewable(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachments')
|
||||
->multiple()
|
||||
->previewable(false)
|
||||
```
|
||||
|
||||
## Moving files instead of copying when the form is submitted
|
||||
|
||||
By default, files are initially uploaded to Livewire's temporary storage directory, and then copied to the destination directory when the form is submitted. If you wish to move the files instead, providing that temporary uploads are stored on the same disk as permanent files, you can use the `moveFiles()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachment')
|
||||
->moveFiles()
|
||||
```
|
||||
|
||||
## Preventing files from being stored permanently
|
||||
|
||||
If you wish to prevent files from being stored permanently when the form is submitted, you can use the `storeFiles(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachment')
|
||||
->storeFiles(false)
|
||||
```
|
||||
|
||||
When the form is submitted, a temporary file upload object will be returned instead of a permanently stored file path. This is perfect for temporary files like imported CSVs.
|
||||
|
||||
Please be aware that images, video and audio files will not show the stored file name in the form's preview, unless you use [`previewable(false)`](#previewing-files). This is due to a limitation with the FilePond preview plugin.
|
||||
|
||||
## Orienting images from their EXIF data
|
||||
|
||||
By default, FilePond will automatically orient images based on their EXIF data. If you wish to disable this behavior, you can use the `orientImagesFromExif(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachment')
|
||||
->orientImagesFromExif(false)
|
||||
```
|
||||
|
||||
## Hiding the remove file button
|
||||
|
||||
It is also possible to hide the remove uploaded file button by using `deletable(false)`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachment')
|
||||
->deletable(false)
|
||||
```
|
||||
|
||||
## Prevent file information fetching
|
||||
|
||||
While the form is loaded, it will automatically detect whether the files exist, what size they are, and what type of files they are. This is all done on the backend. When using remote storage with many files, this can be time-consuming. You can use the `fetchFileInformation(false)` method to disable this feature:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachment')
|
||||
->fetchFileInformation(false)
|
||||
```
|
||||
|
||||
## Customizing the uploading message
|
||||
|
||||
You may customize the uploading message that is displayed in the form's submit button using the `uploadingMessage()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachment')
|
||||
->uploadingMessage('Uploading attachment...')
|
||||
```
|
||||
|
||||
## File upload validation
|
||||
|
||||
As well as all rules listed on the [validation](../validation) page, there are additional rules that are specific to file uploads.
|
||||
|
||||
Since Filament is powered by Livewire and uses its file upload system, you will want to refer to the default Livewire file upload validation rules in the `config/livewire.php` file as well. This also controls the 12MB file size maximum.
|
||||
|
||||
### File type validation
|
||||
|
||||
You may restrict the types of files that may be uploaded using the `acceptedFileTypes()` method, and passing an array of MIME types.
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('document')
|
||||
->acceptedFileTypes(['application/pdf'])
|
||||
```
|
||||
|
||||
You may also use the `image()` method as shorthand to allow all image MIME types.
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('image')
|
||||
->image()
|
||||
```
|
||||
|
||||
### File size validation
|
||||
|
||||
You may also restrict the size of uploaded files in kilobytes:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachment')
|
||||
->minSize(512)
|
||||
->maxSize(1024)
|
||||
```
|
||||
|
||||
### Number of files validation
|
||||
|
||||
You may customize the number of files that may be uploaded, using the `minFiles()` and `maxFiles()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
|
||||
FileUpload::make('attachments')
|
||||
->multiple()
|
||||
->minFiles(2)
|
||||
->maxFiles(5)
|
||||
```
|
||||
69
vendor/filament/forms/docs/03-fields/10-rich-editor.md
vendored
Normal file
69
vendor/filament/forms/docs/03-fields/10-rich-editor.md
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
---
|
||||
title: Rich editor
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
The rich editor allows you to edit and preview HTML content, as well as upload images.
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
|
||||
RichEditor::make('content')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/rich-editor/simple" alt="Rich editor" version="3.x" />
|
||||
|
||||
## Customizing the toolbar buttons
|
||||
|
||||
You may set the toolbar buttons for the editor using the `toolbarButtons()` method. The options shown here are the defaults. In addition to these, `'h1'` is also available:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
|
||||
RichEditor::make('content')
|
||||
->toolbarButtons([
|
||||
'attachFiles',
|
||||
'blockquote',
|
||||
'bold',
|
||||
'bulletList',
|
||||
'codeBlock',
|
||||
'h2',
|
||||
'h3',
|
||||
'italic',
|
||||
'link',
|
||||
'orderedList',
|
||||
'redo',
|
||||
'strike',
|
||||
'underline',
|
||||
'undo',
|
||||
])
|
||||
```
|
||||
|
||||
Alternatively, you may disable specific buttons using the `disableToolbarButtons()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
|
||||
RichEditor::make('content')
|
||||
->disableToolbarButtons([
|
||||
'blockquote',
|
||||
'strike',
|
||||
])
|
||||
```
|
||||
|
||||
To disable all toolbar buttons, set an empty array with `toolbarButtons([])` or use `disableAllToolbarButtons()`.
|
||||
|
||||
## Uploading images to the editor
|
||||
|
||||
You may customize how images are uploaded using configuration methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
|
||||
RichEditor::make('content')
|
||||
->fileAttachmentsDisk('s3')
|
||||
->fileAttachmentsDirectory('attachments')
|
||||
->fileAttachmentsVisibility('private')
|
||||
```
|
||||
68
vendor/filament/forms/docs/03-fields/11-markdown-editor.md
vendored
Normal file
68
vendor/filament/forms/docs/03-fields/11-markdown-editor.md
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: Markdown editor
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
The markdown editor allows you to edit and preview markdown content, as well as upload images using drag and drop.
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\MarkdownEditor;
|
||||
|
||||
MarkdownEditor::make('content')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/markdown-editor/simple" alt="Markdown editor" version="3.x" />
|
||||
|
||||
## Customizing the toolbar buttons
|
||||
|
||||
You may set the toolbar buttons for the editor using the `toolbarButtons()` method. The options shown here are the defaults:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\MarkdownEditor;
|
||||
|
||||
MarkdownEditor::make('content')
|
||||
->toolbarButtons([
|
||||
'attachFiles',
|
||||
'blockquote',
|
||||
'bold',
|
||||
'bulletList',
|
||||
'codeBlock',
|
||||
'heading',
|
||||
'italic',
|
||||
'link',
|
||||
'orderedList',
|
||||
'redo',
|
||||
'strike',
|
||||
'table',
|
||||
'undo',
|
||||
])
|
||||
```
|
||||
|
||||
Alternatively, you may disable specific buttons using the `disableToolbarButtons()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\MarkdownEditor;
|
||||
|
||||
MarkdownEditor::make('content')
|
||||
->disableToolbarButtons([
|
||||
'blockquote',
|
||||
'strike',
|
||||
])
|
||||
```
|
||||
|
||||
To disable all toolbar buttons, set an empty array with `toolbarButtons([])` or use `disableAllToolbarButtons()`.
|
||||
|
||||
## Uploading images to the editor
|
||||
|
||||
You may customize how images are uploaded using configuration methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\MarkdownEditor;
|
||||
|
||||
MarkdownEditor::make('content')
|
||||
->fileAttachmentsDisk('s3')
|
||||
->fileAttachmentsDirectory('attachments')
|
||||
->fileAttachmentsVisibility('private')
|
||||
```
|
||||
710
vendor/filament/forms/docs/03-fields/12-repeater.md
vendored
Normal file
710
vendor/filament/forms/docs/03-fields/12-repeater.md
vendored
Normal file
@@ -0,0 +1,710 @@
|
||||
---
|
||||
title: Repeater
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
The repeater component allows you to output a JSON array of repeated form components.
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
TextInput::make('name')->required(),
|
||||
Select::make('role')
|
||||
->options([
|
||||
'member' => 'Member',
|
||||
'administrator' => 'Administrator',
|
||||
'owner' => 'Owner',
|
||||
])
|
||||
->required(),
|
||||
])
|
||||
->columns(2)
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/repeater/simple" alt="Repeater" version="3.x" />
|
||||
|
||||
We recommend that you store repeater data with a `JSON` column in your database. Additionally, if you're using Eloquent, make sure that column has an `array` cast.
|
||||
|
||||
As evident in the above example, the component schema can be defined within the `schema()` method of the component:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
TextInput::make('name')->required(),
|
||||
// ...
|
||||
])
|
||||
```
|
||||
|
||||
If you wish to define a repeater with multiple schema blocks that can be repeated in any order, please use the [builder](builder).
|
||||
|
||||
## Setting empty default items
|
||||
|
||||
Repeaters may have a certain number of empty items created by default, using the `defaultItems()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->defaultItems(3)
|
||||
```
|
||||
|
||||
Note that these default items are only created when the form is loaded without existing data. Inside [panel resources](../../panels/resources#resource-forms) this only works on Create Pages, as Edit Pages will always fill the data from the model.
|
||||
|
||||
## Adding items
|
||||
|
||||
An action button is displayed below the repeater to allow the user to add a new item.
|
||||
|
||||
## Setting the add action button's label
|
||||
|
||||
You may set a label to customize the text that should be displayed in the button for adding a repeater item, using the `addActionLabel()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->addActionLabel('Add member')
|
||||
```
|
||||
|
||||
### Preventing the user from adding items
|
||||
|
||||
You may prevent the user from adding items to the repeater using the `addable(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->addable(false)
|
||||
```
|
||||
|
||||
## Deleting items
|
||||
|
||||
An action button is displayed on each item to allow the user to delete it.
|
||||
|
||||
### Preventing the user from deleting items
|
||||
|
||||
You may prevent the user from deleting items from the repeater using the `deletable(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->deletable(false)
|
||||
```
|
||||
|
||||
## Reordering items
|
||||
|
||||
A button is displayed on each item to allow the user to drag and drop to reorder it in the list.
|
||||
|
||||
### Preventing the user from reordering items
|
||||
|
||||
You may prevent the user from reordering items from the repeater using the `reorderable(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->reorderable(false)
|
||||
```
|
||||
|
||||
### Reordering items with buttons
|
||||
|
||||
You may use the `reorderableWithButtons()` method to enable reordering items with buttons to move the item up and down:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->reorderableWithButtons()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/repeater/reorderable-with-buttons" alt="Repeater that is reorderable with buttons" version="3.x" />
|
||||
|
||||
### Preventing reordering with drag and drop
|
||||
|
||||
You may use the `reorderableWithDragAndDrop(false)` method to prevent items from being ordered with drag and drop:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->reorderableWithDragAndDrop(false)
|
||||
```
|
||||
|
||||
## Collapsing items
|
||||
|
||||
The repeater may be `collapsible()` to optionally hide content in long forms:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('qualifications')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->collapsible()
|
||||
```
|
||||
|
||||
You may also collapse all items by default:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('qualifications')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->collapsed()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/repeater/collapsed" alt="Collapsed repeater" version="3.x" />
|
||||
|
||||
## Cloning items
|
||||
|
||||
You may allow repeater items to be duplicated using the `cloneable()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('qualifications')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->cloneable()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/repeater/cloneable" alt="Cloneable repeater" version="3.x" />
|
||||
|
||||
## Integrating with an Eloquent relationship
|
||||
|
||||
> If you're building a form inside your Livewire component, make sure you have set up the [form's model](../adding-a-form-to-a-livewire-component#setting-a-form-model). Otherwise, Filament doesn't know which model to use to retrieve the relationship from.
|
||||
|
||||
You may employ the `relationship()` method of the `Repeater` to configure a `HasMany` relationship. Filament will load the item data from the relationship, and save it back to the relationship when the form is submitted. If a custom relationship name is not passed to `relationship()`, Filament will use the field name as the relationship name:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('qualifications')
|
||||
->relationship()
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
```
|
||||
|
||||
When using `disabled()` with `relationship()`, ensure that `disabled()` is called before `relationship()`. This ensures that the `dehydrated()` call from within `relationship()` is not overridden by the call from `disabled()`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('qualifications')
|
||||
->disabled()
|
||||
->relationship()
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
```
|
||||
|
||||
### Reordering items in a relationship
|
||||
|
||||
By default, [reordering](#reordering-items) relationship repeater items is disabled. This is because your related model needs a `sort` column to store the order of related records. To enable reordering, you may use the `orderColumn()` method, passing in a name of the column on your related model to store the order in:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('qualifications')
|
||||
->relationship()
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->orderColumn('sort')
|
||||
```
|
||||
|
||||
If you use something like [`spatie/eloquent-sortable`](https://github.com/spatie/eloquent-sortable) with an order column such as `order_column`, you may pass this in to `orderColumn()`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('qualifications')
|
||||
->relationship()
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->orderColumn('order_column')
|
||||
```
|
||||
|
||||
### Integrating with a `BelongsToMany` Eloquent relationship
|
||||
|
||||
There is a common misconception that using a `BelongsToMany` relationship with a repeater is as simple as using a `HasMany` relationship. This is not the case, as a `BelongsToMany` relationship requires a pivot table to store the relationship data. The repeater saves its data to the related model, not the pivot table. Therefore, if you want to map each repeater item to a row in the pivot table, you must use a `HasMany` relationship with a pivot model to use a repeater with a `BelongsToMany` relationship.
|
||||
|
||||
Imagine you have a form to create a new `Order` model. Each order belongs to many `Product` models, and each product belongs to many orders. You have a `order_product` pivot table to store the relationship data. Instead of using the `products` relationship with the repeater, you should create a new relationship called `orderProducts` on the `Order` model, and use that with the repeater:
|
||||
|
||||
```php
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
public function orderProducts(): HasMany
|
||||
{
|
||||
return $this->hasMany(OrderProduct::class);
|
||||
}
|
||||
```
|
||||
|
||||
If you don't already have an `OrderProduct` pivot model, you should create that, with inverse relationships to `Order` and `Product`:
|
||||
|
||||
```php
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\Pivot;
|
||||
|
||||
class OrderProduct extends Pivot
|
||||
{
|
||||
public function order(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Order::class);
|
||||
}
|
||||
|
||||
public function product(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Product::class);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> Please ensure that your pivot model has a primary key column, like `id`, to allow Filament to keep track of which repeater items have been created, updated and deleted.
|
||||
|
||||
Now you can use the `orderProducts` relationship with the repeater, and it will save the data to the `order_product` pivot table:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Repeater::make('orderProducts')
|
||||
->relationship()
|
||||
->schema([
|
||||
Select::make('product_id')
|
||||
->relationship('product', 'name')
|
||||
->required(),
|
||||
// ...
|
||||
])
|
||||
```
|
||||
|
||||
### Mutating related item data before filling the field
|
||||
|
||||
You may mutate the data for a related item before it is filled into the field using the `mutateRelationshipDataBeforeFillUsing()` method. This method accepts a closure that receives the current item's data in a `$data` variable. You must return the modified array of data:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('qualifications')
|
||||
->relationship()
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->mutateRelationshipDataBeforeFillUsing(function (array $data): array {
|
||||
$data['user_id'] = auth()->id();
|
||||
|
||||
return $data;
|
||||
})
|
||||
```
|
||||
|
||||
### Mutating related item data before creating
|
||||
|
||||
You may mutate the data for a new related item before it is created in the database using the `mutateRelationshipDataBeforeCreateUsing()` method. This method accepts a closure that receives the current item's data in a `$data` variable. You can choose to return either the modified array of data, or `null` to prevent the item from being created:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('qualifications')
|
||||
->relationship()
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->mutateRelationshipDataBeforeCreateUsing(function (array $data): array {
|
||||
$data['user_id'] = auth()->id();
|
||||
|
||||
return $data;
|
||||
})
|
||||
```
|
||||
|
||||
### Mutating related item data before saving
|
||||
|
||||
You may mutate the data for an existing related item before it is saved in the database using the `mutateRelationshipDataBeforeSaveUsing()` method. This method accepts a closure that receives the current item's data in a `$data` variable. You can choose to return either the modified array of data, or `null` to prevent the item from being saved:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('qualifications')
|
||||
->relationship()
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->mutateRelationshipDataBeforeSaveUsing(function (array $data): array {
|
||||
$data['user_id'] = auth()->id();
|
||||
|
||||
return $data;
|
||||
})
|
||||
```
|
||||
|
||||
## Grid layout
|
||||
|
||||
You may organize repeater items into columns by using the `grid()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('qualifications')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->grid(2)
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/repeater/grid" alt="Repeater with a 2 column grid of items" version="3.x" />
|
||||
|
||||
This method accepts the same options as the `columns()` method of the [grid](../layout/grid). This allows you to responsively customize the number of grid columns at various breakpoints.
|
||||
|
||||
## Adding a label to repeater items based on their content
|
||||
|
||||
You may add a label for repeater items using the `itemLabel()` method. This method accepts a closure that receives the current item's data in a `$state` variable. You must return a string to be used as the item label:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
TextInput::make('name')
|
||||
->required()
|
||||
->live(onBlur: true),
|
||||
Select::make('role')
|
||||
->options([
|
||||
'member' => 'Member',
|
||||
'administrator' => 'Administrator',
|
||||
'owner' => 'Owner',
|
||||
])
|
||||
->required(),
|
||||
])
|
||||
->columns(2)
|
||||
->itemLabel(fn (array $state): ?string => $state['name'] ?? null),
|
||||
```
|
||||
|
||||
Any fields that you use from `$state` should be `live()` if you wish to see the item label update live as you use the form.
|
||||
|
||||
<AutoScreenshot name="forms/fields/repeater/labelled" alt="Repeater with item labels" version="3.x" />
|
||||
|
||||
## Simple repeaters with one field
|
||||
|
||||
You can use the `simple()` method to create a repeater with a single field, using a minimal design
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
Repeater::make('invitations')
|
||||
->simple(
|
||||
TextInput::make('email')
|
||||
->email()
|
||||
->required(),
|
||||
)
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/repeater/simple-one-field" alt="Simple repeater design with only one field" version="3.x" />
|
||||
|
||||
Instead of using a nested array to store data, simple repeaters use a flat array of values. This means that the data structure for the above example could look like this:
|
||||
|
||||
```php
|
||||
[
|
||||
'invitations' => [
|
||||
'dan@filamentphp.com',
|
||||
'ryan@filamentphp.com',
|
||||
],
|
||||
],
|
||||
```
|
||||
|
||||
## Using `$get()` to access parent field values
|
||||
|
||||
All form components are able to [use `$get()` and `$set()`](../advanced) to access another field's value. However, you might experience unexpected behavior when using this inside the repeater's schema.
|
||||
|
||||
This is because `$get()` and `$set()`, by default, are scoped to the current repeater item. This means that you are able to interact with another field inside that repeater item easily without knowing which repeater item the current form component belongs to.
|
||||
|
||||
The consequence of this is that you may be confused when you are unable to interact with a field outside the repeater. We use `../` syntax to solve this problem - `$get('../../parent_field_name')`.
|
||||
|
||||
Consider your form has this data structure:
|
||||
|
||||
```php
|
||||
[
|
||||
'client_id' => 1,
|
||||
|
||||
'repeater' => [
|
||||
'item1' => [
|
||||
'service_id' => 2,
|
||||
],
|
||||
],
|
||||
]
|
||||
```
|
||||
|
||||
You are trying to retrieve the value of `client_id` from inside the repeater item.
|
||||
|
||||
`$get()` is relative to the current repeater item, so `$get('client_id')` is looking for `$get('repeater.item1.client_id')`.
|
||||
|
||||
You can use `../` to go up a level in the data structure, so `$get('../client_id')` is `$get('repeater.client_id')` and `$get('../../client_id')` is `$get('client_id')`.
|
||||
|
||||
## Repeater validation
|
||||
|
||||
As well as all rules listed on the [validation](../validation) page, there are additional rules that are specific to repeaters.
|
||||
|
||||
### Number of items validation
|
||||
|
||||
You can validate the minimum and maximum number of items that you can have in a repeater by setting the `minItems()` and `maxItems()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->minItems(2)
|
||||
->maxItems(5)
|
||||
```
|
||||
|
||||
### Distinct state validation
|
||||
|
||||
In many cases, you will want to ensure some sort of uniqueness between repeater items. A couple of common examples could be:
|
||||
|
||||
- Ensuring that only one [checkbox](checkbox) or [toggle](toggle) is activated at once across items in the repeater.
|
||||
- Ensuring that an option may only be selected once across [select](select), [radio](radio), [checkbox list](checkbox-list), or [toggle buttons](toggle-buttons) fields in a repeater.
|
||||
|
||||
You can use the `distinct()` method to validate that the state of a field is unique across all items in the repeater:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Checkbox;
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('answers')
|
||||
->schema([
|
||||
// ...
|
||||
Checkbox::make('is_correct')
|
||||
->distinct(),
|
||||
])
|
||||
```
|
||||
|
||||
The behavior of the `distinct()` validation depends on the data type that the field handles
|
||||
|
||||
- If the field returns a boolean, like a [checkbox](checkbox) or [toggle](toggle), the validation will ensure that only one item has a value of `true`. There may be many fields in the repeater that have a value of `false`.
|
||||
- Otherwise, for fields like a [select](select), [radio](radio), [checkbox list](checkbox-list), or [toggle buttons](toggle-buttons), the validation will ensure that each option may only be selected once across all items in the repeater.
|
||||
|
||||
#### Automatically fixing indistinct state
|
||||
|
||||
If you'd like to automatically fix indistinct state, you can use the `fixIndistinctState()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Checkbox;
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('answers')
|
||||
->schema([
|
||||
// ...
|
||||
Checkbox::make('is_correct')
|
||||
->fixIndistinctState(),
|
||||
])
|
||||
```
|
||||
|
||||
This method will automatically enable the `distinct()` and `live()` methods on the field.
|
||||
|
||||
Depending on the data type that the field handles, the behavior of the `fixIndistinctState()` adapts:
|
||||
|
||||
- If the field returns a boolean, like a [checkbox](checkbox) or [toggle](toggle), and one of the fields is enabled, Filament will automatically disable all other enabled fields on behalf of the user.
|
||||
- Otherwise, for fields like a [select](select), [radio](radio), [checkbox list](checkbox-list), or [toggle buttons](toggle-buttons), when a user selects an option, Filament will automatically deselect all other usages of that option on behalf of the user.
|
||||
|
||||
#### Disabling options when they are already selected in another item
|
||||
|
||||
If you'd like to disable options in a [select](select), [radio](radio), [checkbox list](checkbox-list), or [toggle buttons](toggle-buttons) when they are already selected in another item, you can use the `disableOptionsWhenSelectedInSiblingRepeaterItems()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
use Filament\Forms\Components\Select;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
Select::make('role')
|
||||
->options([
|
||||
// ...
|
||||
])
|
||||
->disableOptionsWhenSelectedInSiblingRepeaterItems(),
|
||||
])
|
||||
```
|
||||
|
||||
This method will automatically enable the `distinct()` and `live()` methods on the field.
|
||||
|
||||
## Customizing the repeater item actions
|
||||
|
||||
This field uses action objects for easy customization of buttons within it. You can customize these buttons by passing a function to an action registration method. The function has access to the `$action` object, which you can use to [customize it](../../actions/trigger-button). The following methods are available to customize the actions:
|
||||
|
||||
- `addAction()`
|
||||
- `cloneAction()`
|
||||
- `collapseAction()`
|
||||
- `collapseAllAction()`
|
||||
- `deleteAction()`
|
||||
- `expandAction()`
|
||||
- `expandAllAction()`
|
||||
- `moveDownAction()`
|
||||
- `moveUpAction()`
|
||||
- `reorderAction()`
|
||||
|
||||
Here is an example of how you might customize an action:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Actions\Action;
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->collapseAllAction(
|
||||
fn (Action $action) => $action->label('Collapse all members'),
|
||||
)
|
||||
```
|
||||
|
||||
### Confirming repeater actions with a modal
|
||||
|
||||
You can confirm actions with a modal by using the `requiresConfirmation()` method on the action object. You may use any [modal customization method](../../actions/modals) to change its content and behavior:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Actions\Action;
|
||||
use Filament\Forms\Components\Repeater;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->deleteAction(
|
||||
fn (Action $action) => $action->requiresConfirmation(),
|
||||
)
|
||||
```
|
||||
|
||||
> The `collapseAction()`, `collapseAllAction()`, `expandAction()`, `expandAllAction()` and `reorderAction()` methods do not support confirmation modals, as clicking their buttons does not make the network request that is required to show the modal.
|
||||
|
||||
### Adding extra item actions to a repeater
|
||||
|
||||
You may add new [action buttons](../actions) to the header of each repeater item by passing `Action` objects into `extraItemActions()`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Actions\Action;
|
||||
use Filament\Forms\Components\Repeater;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
Repeater::make('members')
|
||||
->schema([
|
||||
TextInput::make('email')
|
||||
->label('Email address')
|
||||
->email(),
|
||||
// ...
|
||||
])
|
||||
->extraItemActions([
|
||||
Action::make('sendEmail')
|
||||
->icon('heroicon-m-envelope')
|
||||
->action(function (array $arguments, Repeater $component): void {
|
||||
$itemData = $component->getItemState($arguments['item']);
|
||||
|
||||
Mail::to($itemData['email'])
|
||||
->send(
|
||||
// ...
|
||||
);
|
||||
}),
|
||||
])
|
||||
```
|
||||
|
||||
In this example, `$arguments['item']` gives you the ID of the current repeater item. You can validate the data in that repeater item using the `getItemState()` method on the repeater component. This method returns the validated data for the item. If the item is not valid, it will cancel the action and show an error message for that item in the form.
|
||||
|
||||
If you want to get the raw data from the current item without validating it, you can use `$component->getRawItemState($arguments['item'])` instead.
|
||||
|
||||
If you want to manipulate the raw data for the entire repeater, for example, to add, remove or modify items, you can use `$component->getState()` to get the data, and `$component->state($state)` to set it again:
|
||||
|
||||
```php
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
// Get the raw data for the entire repeater
|
||||
$state = $component->getState();
|
||||
|
||||
// Add an item, with a random UUID as the key
|
||||
$state[Str::uuid()] = [
|
||||
'email' => auth()->user()->email,
|
||||
];
|
||||
|
||||
// Set the new data for the repeater
|
||||
$component->state($state);
|
||||
```
|
||||
|
||||
## Testing repeaters
|
||||
|
||||
Internally, repeaters generate UUIDs for items to keep track of them in the Livewire HTML easier. This means that when you are testing a form with a repeater, you need to ensure that the UUIDs are consistent between the form and the test. This can be tricky, and if you don't do it correctly, your tests can fail as the tests are expecting a UUID, not a numeric key.
|
||||
|
||||
However, since Livewire doesn't need to keep track of the UUIDs in a test, you can disable the UUID generation and replace them with numeric keys, using the `Repeater::fake()` method at the start of your test:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
use function Pest\Livewire\livewire;
|
||||
|
||||
$undoRepeaterFake = Repeater::fake();
|
||||
|
||||
livewire(EditPost::class, ['record' => $post])
|
||||
->assertFormSet([
|
||||
'quotes' => [
|
||||
[
|
||||
'content' => 'First quote',
|
||||
],
|
||||
[
|
||||
'content' => 'Second quote',
|
||||
],
|
||||
],
|
||||
// ...
|
||||
]);
|
||||
|
||||
$undoRepeaterFake();
|
||||
```
|
||||
|
||||
You may also find it useful to access test the number of items in a repeater by passing a function to the `assertFormSet()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Repeater;
|
||||
use function Pest\Livewire\livewire;
|
||||
|
||||
$undoRepeaterFake = Repeater::fake();
|
||||
|
||||
livewire(EditPost::class, ['record' => $post])
|
||||
->assertFormSet(function (array $state) {
|
||||
expect($state['quotes'])
|
||||
->toHaveCount(2);
|
||||
});
|
||||
|
||||
$undoRepeaterFake();
|
||||
```
|
||||
560
vendor/filament/forms/docs/03-fields/13-builder.md
vendored
Normal file
560
vendor/filament/forms/docs/03-fields/13-builder.md
vendored
Normal file
@@ -0,0 +1,560 @@
|
||||
---
|
||||
title: Builder
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
Similar to a [repeater](repeater), the builder component allows you to output a JSON array of repeated form components. Unlike the repeater, which only defines one form schema to repeat, the builder allows you to define different schema "blocks", which you can repeat in any order. This makes it useful for building more advanced array structures.
|
||||
|
||||
The primary use of the builder component is to build web page content using predefined blocks. This could be content for a marketing website, or maybe even fields in an online form. The example below defines multiple blocks for different elements in the page content. On the frontend of your website, you could loop through each block in the JSON and format it how you wish.
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\Textarea;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
Builder\Block::make('heading')
|
||||
->schema([
|
||||
TextInput::make('content')
|
||||
->label('Heading')
|
||||
->required(),
|
||||
Select::make('level')
|
||||
->options([
|
||||
'h1' => 'Heading 1',
|
||||
'h2' => 'Heading 2',
|
||||
'h3' => 'Heading 3',
|
||||
'h4' => 'Heading 4',
|
||||
'h5' => 'Heading 5',
|
||||
'h6' => 'Heading 6',
|
||||
])
|
||||
->required(),
|
||||
])
|
||||
->columns(2),
|
||||
Builder\Block::make('paragraph')
|
||||
->schema([
|
||||
Textarea::make('content')
|
||||
->label('Paragraph')
|
||||
->required(),
|
||||
]),
|
||||
Builder\Block::make('image')
|
||||
->schema([
|
||||
FileUpload::make('url')
|
||||
->label('Image')
|
||||
->image()
|
||||
->required(),
|
||||
TextInput::make('alt')
|
||||
->label('Alt text')
|
||||
->required(),
|
||||
]),
|
||||
])
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/builder/simple" alt="Builder" version="3.x" />
|
||||
|
||||
We recommend that you store builder data with a `JSON` column in your database. Additionally, if you're using Eloquent, make sure that column has an `array` cast.
|
||||
|
||||
As evident in the above example, blocks can be defined within the `blocks()` method of the component. Blocks are `Builder\Block` objects, and require a unique name, and a component schema:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
Builder\Block::make('heading')
|
||||
->schema([
|
||||
TextInput::make('content')->required(),
|
||||
// ...
|
||||
]),
|
||||
// ...
|
||||
])
|
||||
```
|
||||
|
||||
## Setting a block's label
|
||||
|
||||
By default, the label of the block will be automatically determined based on its name. To override the block's label, you may use the `label()` method. Customizing the label in this way is useful if you wish to use a [translation string for localization](https://laravel.com/docs/localization#retrieving-translation-strings):
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder\Block::make('heading')
|
||||
->label(__('blocks.heading'))
|
||||
```
|
||||
|
||||
### Labelling builder items based on their content
|
||||
|
||||
You may add a label for a builder item using the same `label()` method. This method accepts a closure that receives the item's data in a `$state` variable. If `$state` is null, you should return the block label that should be displayed in the block picker. Otherwise, you should return a string to be used as the item label:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
Builder\Block::make('heading')
|
||||
->schema([
|
||||
TextInput::make('content')
|
||||
->live(onBlur: true)
|
||||
->required(),
|
||||
// ...
|
||||
])
|
||||
->label(function (?array $state): string {
|
||||
if ($state === null) {
|
||||
return 'Heading';
|
||||
}
|
||||
|
||||
return $state['content'] ?? 'Untitled heading';
|
||||
})
|
||||
```
|
||||
|
||||
Any fields that you use from `$state` should be `live()` if you wish to see the item label update live as you use the form.
|
||||
|
||||
<AutoScreenshot name="forms/fields/builder/labelled" alt="Builder with labelled blocks based on the content" version="3.x" />
|
||||
|
||||
### Numbering builder items
|
||||
|
||||
By default, items in the builder have a number next to their label. You may disable this using the `blockNumbers(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
->blockNumbers(false)
|
||||
```
|
||||
|
||||
## Setting a block's icon
|
||||
|
||||
Blocks may also have an [icon](https://blade-ui-kit.com/blade-icons?set=1#search), which is displayed next to the label. You can add an icon by passing its name to the `icon()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder\Block::make('paragraph')
|
||||
->icon('heroicon-m-bars-3-bottom-left')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/builder/icons" alt="Builder with block icons in the dropdown" version="3.x" />
|
||||
|
||||
## Adding items
|
||||
|
||||
An action button is displayed below the builder to allow the user to add a new item.
|
||||
|
||||
## Setting the add action button's label
|
||||
|
||||
You may set a label to customize the text that should be displayed in the button for adding a builder item, using the `addActionLabel()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
->addActionLabel('Add a new block')
|
||||
```
|
||||
|
||||
### Preventing the user from adding items
|
||||
|
||||
You may prevent the user from adding items to the builder using the `addable(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
->addable(false)
|
||||
```
|
||||
|
||||
## Deleting items
|
||||
|
||||
An action button is displayed on each item to allow the user to delete it.
|
||||
|
||||
### Preventing the user from deleting items
|
||||
|
||||
You may prevent the user from deleting items from the builder using the `deletable(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
->deletable(false)
|
||||
```
|
||||
|
||||
## Reordering items
|
||||
|
||||
A button is displayed on each item to allow the user to drag and drop to reorder it in the list.
|
||||
|
||||
### Preventing the user from reordering items
|
||||
|
||||
You may prevent the user from reordering items from the builder using the `reorderable(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
->reorderable(false)
|
||||
```
|
||||
|
||||
### Reordering items with buttons
|
||||
|
||||
You may use the `reorderableWithButtons()` method to enable reordering items with buttons to move the item up and down:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
->reorderableWithButtons()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/builder/reorderable-with-buttons" alt="Builder that is reorderable with buttons" version="3.x" />
|
||||
|
||||
### Preventing reordering with drag and drop
|
||||
|
||||
You may use the `reorderableWithDragAndDrop(false)` method to prevent items from being ordered with drag and drop:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
->reorderableWithDragAndDrop(false)
|
||||
```
|
||||
|
||||
## Collapsing items
|
||||
|
||||
The builder may be `collapsible()` to optionally hide content in long forms:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
->collapsible()
|
||||
```
|
||||
|
||||
You may also collapse all items by default:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
->collapsed()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/builder/collapsed" alt="Collapsed builder" version="3.x" />
|
||||
|
||||
## Cloning items
|
||||
|
||||
You may allow builder items to be duplicated using the `cloneable()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
->cloneable()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/builder/cloneable" alt="Builder repeater" version="3.x" />
|
||||
|
||||
## Customizing the block picker
|
||||
|
||||
### Changing the number of columns in the block picker
|
||||
|
||||
The block picker has only 1 column. You may customize it by passing a number of columns to `blockPickerColumns()`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make()
|
||||
->blockPickerColumns(2)
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
```
|
||||
|
||||
This method can be used in a couple of different ways:
|
||||
|
||||
- You can pass an integer like `blockPickerColumns(2)`. This integer is the number of columns used on the `lg` breakpoint and higher. All smaller devices will have just 1 column.
|
||||
- You can pass an array, where the key is the breakpoint and the value is the number of columns. For example, `blockPickerColumns(['md' => 2, 'xl' => 4])` will create a 2 column layout on medium devices, and a 4 column layout on extra large devices. The default breakpoint for smaller devices uses 1 column, unless you use a `default` array key.
|
||||
|
||||
Breakpoints (`sm`, `md`, `lg`, `xl`, `2xl`) are defined by Tailwind, and can be found in the [Tailwind documentation](https://tailwindcss.com/docs/responsive-design#overview).
|
||||
|
||||
### Increasing the width of the block picker
|
||||
|
||||
When you [increase the number of columns](#changing-the-number-of-columns-in-the-block-picker), the width of the dropdown should increase incrementally to handle the additional columns. If you'd like more control, you can manually set a maximum width for the dropdown using the `blockPickerWidth()` method. Options correspond to [Tailwind's max-width scale](https://tailwindcss.com/docs/max-width). The options are `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `4xl`, `5xl`, `6xl`, `7xl`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make()
|
||||
->blockPickerColumns(3)
|
||||
->blockPickerWidth('2xl')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
```
|
||||
|
||||
## Limiting the number of times a block can be used
|
||||
|
||||
By default, each block can be used in the builder an unlimited number of times. You may limit this using the `maxItems()` method on a block:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder\Block::make('heading')
|
||||
->schema([
|
||||
// ...
|
||||
])
|
||||
->maxItems(1)
|
||||
```
|
||||
|
||||
## Builder validation
|
||||
|
||||
As well as all rules listed on the [validation](../validation) page, there are additional rules that are specific to builders.
|
||||
|
||||
### Number of items validation
|
||||
|
||||
You can validate the minimum and maximum number of items that you can have in a builder by setting the `minItems()` and `maxItems()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
->minItems(1)
|
||||
->maxItems(5)
|
||||
```
|
||||
|
||||
## Customizing the builder item actions
|
||||
|
||||
This field uses action objects for easy customization of buttons within it. You can customize these buttons by passing a function to an action registration method. The function has access to the `$action` object, which you can use to [customize it](../../actions/trigger-button). The following methods are available to customize the actions:
|
||||
|
||||
- `addAction()`
|
||||
- `addBetweenAction()`
|
||||
- `cloneAction()`
|
||||
- `collapseAction()`
|
||||
- `collapseAllAction()`
|
||||
- `deleteAction()`
|
||||
- `expandAction()`
|
||||
- `expandAllAction()`
|
||||
- `moveDownAction()`
|
||||
- `moveUpAction()`
|
||||
- `reorderAction()`
|
||||
|
||||
Here is an example of how you might customize an action:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Actions\Action;
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
->collapseAllAction(
|
||||
fn (Action $action) => $action->label('Collapse all content'),
|
||||
)
|
||||
```
|
||||
|
||||
### Confirming builder actions with a modal
|
||||
|
||||
You can confirm actions with a modal by using the `requiresConfirmation()` method on the action object. You may use any [modal customization method](../../actions/modals) to change its content and behavior:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Actions\Action;
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
// ...
|
||||
])
|
||||
->deleteAction(
|
||||
fn (Action $action) => $action->requiresConfirmation(),
|
||||
)
|
||||
```
|
||||
|
||||
> The `addAction()`, `addBetweenAction()`, `collapseAction()`, `collapseAllAction()`, `expandAction()`, `expandAllAction()` and `reorderAction()` methods do not support confirmation modals, as clicking their buttons does not make the network request that is required to show the modal.
|
||||
|
||||
### Adding extra item actions to a builder
|
||||
|
||||
You may add new [action buttons](../actions) to the header of each builder item by passing `Action` objects into `extraItemActions()`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Actions\Action;
|
||||
use Filament\Forms\Components\Builder;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
Builder::make('content')
|
||||
->blocks([
|
||||
Builder\Block::make('contactDetails')
|
||||
->schema([
|
||||
TextInput::make('email')
|
||||
->label('Email address')
|
||||
->email()
|
||||
->required(),
|
||||
// ...
|
||||
]),
|
||||
// ...
|
||||
])
|
||||
->extraItemActions([
|
||||
Action::make('sendEmail')
|
||||
->icon('heroicon-m-square-2-stack')
|
||||
->action(function (array $arguments, Builder $component): void {
|
||||
$itemData = $component->getItemState($arguments['item']);
|
||||
|
||||
Mail::to($itemData['email'])
|
||||
->send(
|
||||
// ...
|
||||
);
|
||||
}),
|
||||
])
|
||||
```
|
||||
|
||||
In this example, `$arguments['item']` gives you the ID of the current builder item. You can validate the data in that builder item using the `getItemState()` method on the builder component. This method returns the validated data for the item. If the item is not valid, it will cancel the action and show an error message for that item in the form.
|
||||
|
||||
If you want to get the raw data from the current item without validating it, you can use `$component->getRawItemState($arguments['item'])` instead.
|
||||
|
||||
If you want to manipulate the raw data for the entire builder, for example, to add, remove or modify items, you can use `$component->getState()` to get the data, and `$component->state($state)` to set it again:
|
||||
|
||||
```php
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
// Get the raw data for the entire builder
|
||||
$state = $component->getState();
|
||||
|
||||
// Add an item, with a random UUID as the key
|
||||
$state[Str::uuid()] = [
|
||||
'type' => 'contactDetails',
|
||||
'data' => [
|
||||
'email' => auth()->user()->email,
|
||||
],
|
||||
];
|
||||
|
||||
// Set the new data for the builder
|
||||
$component->state($state);
|
||||
```
|
||||
|
||||
## Previewing blocks
|
||||
|
||||
If you prefer to render read-only previews in the builder instead of the blocks' forms, you can use the `blockPreviews()` method. This will render each block's `preview()` instead of the form. Block data will be passed to the preview Blade view in a variable with the same name:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
use Filament\Forms\Components\Builder\Block;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
|
||||
Builder::make('content')
|
||||
->blockPreviews()
|
||||
->blocks([
|
||||
Block::make('heading')
|
||||
->schema([
|
||||
TextInput::make('text')
|
||||
->placeholder('Default heading'),
|
||||
])
|
||||
->preview('filament.content.blocks-previews.heading'),
|
||||
])
|
||||
```
|
||||
|
||||
In `/resources/views/filament/content/block-previews/heading.blade.php`, you can access the block data like so:
|
||||
|
||||
```blade
|
||||
<h1>
|
||||
{{ $text ?? 'Default heading' }}
|
||||
</h1>
|
||||
```
|
||||
|
||||
### Interactive block previews
|
||||
|
||||
By default, preview content is not interactive, and clicking it will open the Edit modal for that block to manage its settings. If you have links and buttons that you'd like to remain interactive in the block previews, you can use the `areInteractive: true` argument of the `blockPreviews()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
Builder::make('content')
|
||||
->blockPreviews(areInteractive: true)
|
||||
->blocks([
|
||||
//
|
||||
])
|
||||
```
|
||||
|
||||
## Testing builders
|
||||
|
||||
Internally, builders generate UUIDs for items to keep track of them in the Livewire HTML easier. This means that when you are testing a form with a builder, you need to ensure that the UUIDs are consistent between the form and the test. This can be tricky, and if you don't do it correctly, your tests can fail as the tests are expecting a UUID, not a numeric key.
|
||||
|
||||
However, since Livewire doesn't need to keep track of the UUIDs in a test, you can disable the UUID generation and replace them with numeric keys, using the `Builder::fake()` method at the start of your test:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
use function Pest\Livewire\livewire;
|
||||
|
||||
$undoBuilderFake = Builder::fake();
|
||||
|
||||
livewire(EditPost::class, ['record' => $post])
|
||||
->assertFormSet([
|
||||
'content' => [
|
||||
[
|
||||
'type' => 'heading',
|
||||
'data' => [
|
||||
'content' => 'Hello, world!',
|
||||
'level' => 'h1',
|
||||
],
|
||||
],
|
||||
[
|
||||
'type' => 'paragraph',
|
||||
'data' => [
|
||||
'content' => 'This is a test post.',
|
||||
],
|
||||
],
|
||||
],
|
||||
// ...
|
||||
]);
|
||||
|
||||
$undoBuilderFake();
|
||||
```
|
||||
|
||||
You may also find it useful to access test the number of items in a repeater by passing a function to the `assertFormSet()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Builder;
|
||||
use function Pest\Livewire\livewire;
|
||||
|
||||
$undoBuilderFake = Builder::fake();
|
||||
|
||||
livewire(EditPost::class, ['record' => $post])
|
||||
->assertFormSet(function (array $state) {
|
||||
expect($state['content'])
|
||||
->toHaveCount(2);
|
||||
});
|
||||
|
||||
$undoBuilderFake();
|
||||
```
|
||||
122
vendor/filament/forms/docs/03-fields/14-tags-input.md
vendored
Normal file
122
vendor/filament/forms/docs/03-fields/14-tags-input.md
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
---
|
||||
title: Tags input
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
The tags input component allows you to interact with a list of tags.
|
||||
|
||||
By default, tags are stored in JSON:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TagsInput;
|
||||
|
||||
TagsInput::make('tags')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/tags-input/simple" alt="Tags input" version="3.x" />
|
||||
|
||||
If you're saving the JSON tags using Eloquent, you should be sure to add an `array` [cast](https://laravel.com/docs/eloquent-mutators#array-and-json-casting) to the model property:
|
||||
|
||||
```php
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Post extends Model
|
||||
{
|
||||
protected $casts = [
|
||||
'tags' => 'array',
|
||||
];
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
> Filament also supports [`spatie/laravel-tags`](https://github.com/spatie/laravel-tags). See our [plugin documentation](/plugins/filament-spatie-tags) for more information.
|
||||
|
||||
## Comma-separated tags
|
||||
|
||||
You may allow the tags to be stored in a separated string, instead of JSON. To set this up, pass the separating character to the `separator()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TagsInput;
|
||||
|
||||
TagsInput::make('tags')
|
||||
->separator(',')
|
||||
```
|
||||
|
||||
## Autocompleting tag suggestions
|
||||
|
||||
Tags inputs may have autocomplete suggestions. To enable this, pass an array of suggestions to the `suggestions()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TagsInput;
|
||||
|
||||
TagsInput::make('tags')
|
||||
->suggestions([
|
||||
'tailwindcss',
|
||||
'alpinejs',
|
||||
'laravel',
|
||||
'livewire',
|
||||
])
|
||||
```
|
||||
|
||||
## Defining split keys
|
||||
|
||||
Split keys allow you to map specific buttons on your user's keyboard to create a new tag. By default, when the user presses "Enter", a new tag is created in the input. You may also define other keys to create new tags, such as "Tab" or " ". To do this, pass an array of keys to the `splitKeys()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TagsInput;
|
||||
|
||||
TagsInput::make('tags')
|
||||
->splitKeys(['Tab', ' '])
|
||||
```
|
||||
|
||||
You can [read more about possible options for keys](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key).
|
||||
|
||||
## Adding a prefix and suffix to individual tags
|
||||
|
||||
You can add prefix and suffix to tags without modifying the real state of the field. This can be useful if you need to show presentational formatting to users without saving it. This is done with the `tagPrefix()` or `tagSuffix()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TagsInput;
|
||||
|
||||
TagsInput::make('percentages')
|
||||
->tagSuffix('%')
|
||||
```
|
||||
|
||||
## Reordering tags
|
||||
|
||||
You can allow the user to reorder tags within the field using the `reorderable()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TagsInput;
|
||||
|
||||
TagsInput::make('tags')
|
||||
->reorderable()
|
||||
```
|
||||
|
||||
## Changing the color of tags
|
||||
|
||||
You can change the color of the tags by passing a color to the `color()` method. It may be either `danger`, `gray`, `info`, `primary`, `success` or `warning`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TagsInput;
|
||||
|
||||
TagsInput::make('tags')
|
||||
->color('danger')
|
||||
```
|
||||
|
||||
## Tags validation
|
||||
|
||||
You may add validation rules for each tag by passing an array of rules to the `nestedRecursiveRules()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\TagsInput;
|
||||
|
||||
TagsInput::make('tags')
|
||||
->nestedRecursiveRules([
|
||||
'min:3',
|
||||
'max:255',
|
||||
])
|
||||
```
|
||||
81
vendor/filament/forms/docs/03-fields/15-textarea.md
vendored
Normal file
81
vendor/filament/forms/docs/03-fields/15-textarea.md
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
---
|
||||
title: Textarea
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
The textarea allows you to interact with a multi-line string:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Textarea;
|
||||
|
||||
Textarea::make('description')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/textarea/simple" alt="Textarea" version="3.x" />
|
||||
|
||||
## Resizing the textarea
|
||||
|
||||
You may change the size of the textarea by defining the `rows()` and `cols()` methods:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Textarea;
|
||||
|
||||
Textarea::make('description')
|
||||
->rows(10)
|
||||
->cols(20)
|
||||
```
|
||||
|
||||
### Autosizing the textarea
|
||||
|
||||
You may allow the textarea to automatically resize to fit its content by setting the `autosize()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Textarea;
|
||||
|
||||
Textarea::make('description')
|
||||
->autosize()
|
||||
```
|
||||
|
||||
## Making the field read-only
|
||||
|
||||
Not to be confused with [disabling the field](getting-started#disabling-a-field), you may make the field "read-only" using the `readOnly()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Textarea;
|
||||
|
||||
Textarea::make('description')
|
||||
->readOnly()
|
||||
```
|
||||
|
||||
There are a few differences, compared to [`disabled()`](getting-started#disabling-a-field):
|
||||
|
||||
- When using `readOnly()`, the field will still be sent to the server when the form is submitted. It can be mutated with the browser console, or via JavaScript. You can use [`dehydrated(false)`](advanced#preventing-a-field-from-being-dehydrated) to prevent this.
|
||||
- There are no styling changes, such as less opacity, when using `readOnly()`.
|
||||
- The field is still focusable when using `readOnly()`.
|
||||
|
||||
## Textarea validation
|
||||
|
||||
As well as all rules listed on the [validation](../validation) page, there are additional rules that are specific to textareas.
|
||||
|
||||
### Length validation
|
||||
|
||||
You may limit the length of the textarea by setting the `minLength()` and `maxLength()` methods. These methods add both frontend and backend validation:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Textarea;
|
||||
|
||||
Textarea::make('description')
|
||||
->minLength(2)
|
||||
->maxLength(1024)
|
||||
```
|
||||
|
||||
You can also specify the exact length of the textarea by setting the `length()`. This method adds both frontend and backend validation:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Textarea;
|
||||
|
||||
Textarea::make('question')
|
||||
->length(100)
|
||||
```
|
||||
175
vendor/filament/forms/docs/03-fields/16-key-value.md
vendored
Normal file
175
vendor/filament/forms/docs/03-fields/16-key-value.md
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
---
|
||||
title: Key-value
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
The key-value field allows you to interact with one-dimensional JSON object:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\KeyValue;
|
||||
|
||||
KeyValue::make('meta')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/key-value/simple" alt="Key-value" version="3.x" />
|
||||
|
||||
If you're saving the data in Eloquent, you should be sure to add an `array` [cast](https://laravel.com/docs/eloquent-mutators#array-and-json-casting) to the model property:
|
||||
|
||||
```php
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Post extends Model
|
||||
{
|
||||
protected $casts = [
|
||||
'meta' => 'array',
|
||||
];
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Adding rows
|
||||
|
||||
An action button is displayed below the field to allow the user to add a new row.
|
||||
|
||||
## Setting the add action button's label
|
||||
|
||||
You may set a label to customize the text that should be displayed in the button for adding a row, using the `addActionLabel()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\KeyValue;
|
||||
|
||||
KeyValue::make('meta')
|
||||
->addActionLabel('Add property')
|
||||
```
|
||||
|
||||
### Preventing the user from adding rows
|
||||
|
||||
You may prevent the user from adding rows using the `addable(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\KeyValue;
|
||||
|
||||
KeyValue::make('meta')
|
||||
->addable(false)
|
||||
```
|
||||
|
||||
## Deleting rows
|
||||
|
||||
An action button is displayed on each item to allow the user to delete it.
|
||||
|
||||
### Preventing the user from deleting rows
|
||||
|
||||
You may prevent the user from deleting rows using the `deletable(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\KeyValue;
|
||||
|
||||
KeyValue::make('meta')
|
||||
->deletable(false)
|
||||
```
|
||||
|
||||
## Editing keys
|
||||
|
||||
### Customizing the key fields' label
|
||||
|
||||
You may customize the label for the key fields using the `keyLabel()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\KeyValue;
|
||||
|
||||
KeyValue::make('meta')
|
||||
->keyLabel('Property name')
|
||||
```
|
||||
|
||||
### Adding key field placeholders
|
||||
|
||||
You may also add placeholders for the key fields using the `keyPlaceholder()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\KeyValue;
|
||||
|
||||
KeyValue::make('meta')
|
||||
->keyPlaceholder('Property name')
|
||||
```
|
||||
|
||||
### Preventing the user from editing keys
|
||||
|
||||
You may prevent the user from editing keys using the `editableKeys(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\KeyValue;
|
||||
|
||||
KeyValue::make('meta')
|
||||
->editableKeys(false)
|
||||
```
|
||||
|
||||
## Editing values
|
||||
|
||||
### Customizing the value fields' label
|
||||
|
||||
You may customize the label for the value fields using the `valueLabel()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\KeyValue;
|
||||
|
||||
KeyValue::make('meta')
|
||||
->valueLabel('Property value')
|
||||
```
|
||||
|
||||
### Adding value field placeholders
|
||||
|
||||
You may also add placeholders for the value fields using the `valuePlaceholder()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\KeyValue;
|
||||
|
||||
KeyValue::make('meta')
|
||||
->valuePlaceholder('Property value')
|
||||
```
|
||||
|
||||
### Preventing the user from editing values
|
||||
|
||||
You may prevent the user from editing values using the `editableValues(false)` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\KeyValue;
|
||||
|
||||
KeyValue::make('meta')
|
||||
->editableValues(false)
|
||||
```
|
||||
|
||||
## Reordering rows
|
||||
|
||||
You can allow the user to reorder rows within the table using the `reorderable()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\KeyValue;
|
||||
|
||||
KeyValue::make('meta')
|
||||
->reorderable()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/key-value/reorderable" alt="Key-value with reorderable rows" version="3.x" />
|
||||
|
||||
## Customizing the key-value action objects
|
||||
|
||||
This field uses action objects for easy customization of buttons within it. You can customize these buttons by passing a function to an action registration method. The function has access to the `$action` object, which you can use to [customize it](../../actions/trigger-button). The following methods are available to customize the actions:
|
||||
|
||||
- `addAction()`
|
||||
- `deleteAction()`
|
||||
- `reorderAction()`
|
||||
|
||||
Here is an example of how you might customize an action:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Actions\Action;
|
||||
use Filament\Forms\Components\KeyValue;
|
||||
|
||||
KeyValue::make('meta')
|
||||
->deleteAction(
|
||||
fn (Action $action) => $action->icon('heroicon-m-x-mark'),
|
||||
)
|
||||
```
|
||||
35
vendor/filament/forms/docs/03-fields/17-color-picker.md
vendored
Normal file
35
vendor/filament/forms/docs/03-fields/17-color-picker.md
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
title: Color picker
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
The color picker component allows you to pick a color in a range of formats.
|
||||
|
||||
By default, the component uses HEX format:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\ColorPicker;
|
||||
|
||||
ColorPicker::make('color')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/color-picker/simple" alt="Color picker" version="3.x" />
|
||||
|
||||
## Setting the color format
|
||||
|
||||
While HEX format is used by default, you can choose which color format to use:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\ColorPicker;
|
||||
|
||||
ColorPicker::make('hsl_color')
|
||||
->hsl()
|
||||
|
||||
ColorPicker::make('rgb_color')
|
||||
->rgb()
|
||||
|
||||
ColorPicker::make('rgba_color')
|
||||
->rgba()
|
||||
```
|
||||
211
vendor/filament/forms/docs/03-fields/18-toggle-buttons.md
vendored
Normal file
211
vendor/filament/forms/docs/03-fields/18-toggle-buttons.md
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
---
|
||||
title: Toggle buttons
|
||||
---
|
||||
import AutoScreenshot from "@components/AutoScreenshot.astro"
|
||||
|
||||
## Overview
|
||||
|
||||
The toggle buttons input provides a group of buttons for selecting a single value, or multiple values, from a list of predefined options:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\ToggleButtons;
|
||||
|
||||
ToggleButtons::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'scheduled' => 'Scheduled',
|
||||
'published' => 'Published'
|
||||
])
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle-buttons/simple" alt="Toggle buttons" version="3.x" />
|
||||
|
||||
## Changing the color of option buttons
|
||||
|
||||
You can change the color of the option buttons using the `colors()` method. Each key in the array should correspond to an option value, and the value may be either `danger`, `gray`, `info`, `primary`, `success` or `warning`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\ToggleButtons;
|
||||
|
||||
ToggleButtons::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'scheduled' => 'Scheduled',
|
||||
'published' => 'Published'
|
||||
])
|
||||
->colors([
|
||||
'draft' => 'info',
|
||||
'scheduled' => 'warning',
|
||||
'published' => 'success',
|
||||
])
|
||||
```
|
||||
|
||||
If you are using an enum for the options, you can use the [`HasColor` interface](../../support/enums#enum-colors) to define colors instead.
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle-buttons/colors" alt="Toggle buttons with different colors" version="3.x" />
|
||||
|
||||
## Adding icons to option buttons
|
||||
|
||||
You can add [icon](https://blade-ui-kit.com/blade-icons?set=1#search) to the option buttons using the `icons()` method. Each key in the array should correspond to an option value, and the value may be any valid [Blade icon](https://blade-ui-kit.com/blade-icons?set=1#search):
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\ToggleButtons;
|
||||
|
||||
ToggleButtons::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'scheduled' => 'Scheduled',
|
||||
'published' => 'Published'
|
||||
])
|
||||
->icons([
|
||||
'draft' => 'heroicon-o-pencil',
|
||||
'scheduled' => 'heroicon-o-clock',
|
||||
'published' => 'heroicon-o-check-circle',
|
||||
])
|
||||
```
|
||||
|
||||
If you are using an enum for the options, you can use the [`HasIcon` interface](../../support/enums#enum-icons) to define icons instead.
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle-buttons/icons" alt="Toggle buttons with icons" version="3.x" />
|
||||
|
||||
## Boolean options
|
||||
|
||||
If you want a simple boolean toggle button group, with "Yes" and "No" options, you can use the `boolean()` method:
|
||||
|
||||
```php
|
||||
ToggleButtons::make('feedback')
|
||||
->label('Like this post?')
|
||||
->boolean()
|
||||
```
|
||||
|
||||
The options will have [colors](#changing-the-color-of-option-buttons) and [icons](#adding-icons-to-option-buttons) set up automatically, but you can override these with `colors()` or `icons()`.
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle-buttons/boolean" alt="Boolean toggle buttons" version="3.x" />
|
||||
|
||||
## Positioning the options inline with each other
|
||||
|
||||
You may wish to display the options `inline()` with each other:
|
||||
|
||||
```php
|
||||
ToggleButtons::make('feedback')
|
||||
->label('Like this post?')
|
||||
->boolean()
|
||||
->inline()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle-buttons/inline" alt="Inline toggle buttons" version="3.x" />
|
||||
|
||||
## Grouping option buttons
|
||||
|
||||
You may wish to group option buttons together so they are more compact, using the `grouped()` method. This also makes them appear horizontally inline with each other:
|
||||
|
||||
```php
|
||||
ToggleButtons::make('feedback')
|
||||
->label('Like this post?')
|
||||
->boolean()
|
||||
->grouped()
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle-buttons/grouped" alt="Grouped toggle buttons" version="3.x" />
|
||||
|
||||
## Selecting multiple buttons
|
||||
|
||||
The `multiple()` method on the `ToggleButtons` component allows you to select multiple values from the list of options:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\ToggleButtons;
|
||||
|
||||
ToggleButtons::make('technologies')
|
||||
->multiple()
|
||||
->options([
|
||||
'tailwind' => 'Tailwind CSS',
|
||||
'alpine' => 'Alpine.js',
|
||||
'laravel' => 'Laravel',
|
||||
'livewire' => 'Laravel Livewire',
|
||||
])
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle-buttons/multiple" alt="Multiple toggle buttons selected" version="3.x" />
|
||||
|
||||
These options are returned in JSON format. If you're saving them using Eloquent, you should be sure to add an `array` [cast](https://laravel.com/docs/eloquent-mutators#array-and-json-casting) to the model property:
|
||||
|
||||
```php
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class App extends Model
|
||||
{
|
||||
protected $casts = [
|
||||
'technologies' => 'array',
|
||||
];
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## Splitting options into columns
|
||||
|
||||
You may split options into columns by using the `columns()` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\ToggleButtons;
|
||||
|
||||
ToggleButtons::make('technologies')
|
||||
->options([
|
||||
// ...
|
||||
])
|
||||
->columns(2)
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle-buttons/columns" alt="Toggle buttons with 2 columns" version="3.x" />
|
||||
|
||||
This method accepts the same options as the `columns()` method of the [grid](layout/grid). This allows you to responsively customize the number of columns at various breakpoints.
|
||||
|
||||
### Setting the grid direction
|
||||
|
||||
By default, when you arrange buttons into columns, they will be listed in order vertically. If you'd like to list them horizontally, you may use the `gridDirection('row')` method:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\ToggleButtons;
|
||||
|
||||
ToggleButtons::make('technologies')
|
||||
->options([
|
||||
// ...
|
||||
])
|
||||
->columns(2)
|
||||
->gridDirection('row')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle-buttons/rows" alt="Toggle buttons with 2 rows" version="3.x" />
|
||||
|
||||
## Disabling specific options
|
||||
|
||||
You can disable specific options using the `disableOptionWhen()` method. It accepts a closure, in which you can check if the option with a specific `$value` should be disabled:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\ToggleButtons;
|
||||
|
||||
ToggleButtons::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'scheduled' => 'Scheduled',
|
||||
'published' => 'Published',
|
||||
])
|
||||
->disableOptionWhen(fn (string $value): bool => $value === 'published')
|
||||
```
|
||||
|
||||
<AutoScreenshot name="forms/fields/toggle-buttons/disabled-option" alt="Toggle buttons with disabled option" version="3.x" />
|
||||
|
||||
If you want to retrieve the options that have not been disabled, e.g. for validation purposes, you can do so using `getEnabledOptions()`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\ToggleButtons;
|
||||
|
||||
ToggleButtons::make('status')
|
||||
->options([
|
||||
'draft' => 'Draft',
|
||||
'scheduled' => 'Scheduled',
|
||||
'published' => 'Published',
|
||||
])
|
||||
->disableOptionWhen(fn (string $value): bool => $value === 'published')
|
||||
->in(fn (ToggleButtons $component): array => array_keys($component->getEnabledOptions()))
|
||||
```
|
||||
15
vendor/filament/forms/docs/03-fields/19-hidden.md
vendored
Normal file
15
vendor/filament/forms/docs/03-fields/19-hidden.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: Hidden
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The hidden component allows you to create a hidden field in your form that holds a value.
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Hidden;
|
||||
|
||||
Hidden::make('token')
|
||||
```
|
||||
|
||||
Please be aware that the value of this field is still editable by the user if they decide to use the browser's developer tools. You should not use this component to store sensitive or read-only information.
|
||||
141
vendor/filament/forms/docs/03-fields/20-custom.md
vendored
Normal file
141
vendor/filament/forms/docs/03-fields/20-custom.md
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
---
|
||||
title: Custom fields
|
||||
---
|
||||
import LaracastsBanner from "@components/LaracastsBanner.astro"
|
||||
|
||||
<LaracastsBanner
|
||||
title="Build a Custom Form Field"
|
||||
description="Watch the Build Advanced Components for Filament series on Laracasts - it will teach you how to build components, and you'll get to know all the internal tools to help you."
|
||||
url="https://laracasts.com/series/build-advanced-components-for-filament/episodes/6"
|
||||
series="building-advanced-components"
|
||||
/>
|
||||
|
||||
## View fields
|
||||
|
||||
Aside from [building custom fields](#custom-field-classes), you may create "view" fields which allow you to create custom fields without extra PHP classes.
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\ViewField;
|
||||
|
||||
ViewField::make('rating')
|
||||
->view('filament.forms.components.range-slider')
|
||||
```
|
||||
|
||||
This assumes that you have a `resources/views/filament/forms/components/range-slider.blade.php` file.
|
||||
|
||||
### Passing data to view fields
|
||||
|
||||
You can pass a simple array of data to the view using `viewData()`:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\ViewField;
|
||||
|
||||
ViewField::make('rating')
|
||||
->view('filament.forms.components.range-slider')
|
||||
->viewData([
|
||||
'min' => 1,
|
||||
'max' => 5,
|
||||
])
|
||||
```
|
||||
|
||||
However, more complex configuration can be achieved with a [custom field class](#custom-field-classes).
|
||||
|
||||
## Custom field classes
|
||||
|
||||
You may create your own custom field classes and views, which you can reuse across your project, and even release as a plugin to the community.
|
||||
|
||||
> If you're just creating a simple custom field to use once, you could instead use a [view field](#view) to render any custom Blade file.
|
||||
|
||||
To create a custom field class and view, you may use the following command:
|
||||
|
||||
```bash
|
||||
php artisan make:form-field RangeSlider
|
||||
```
|
||||
|
||||
This will create the following field class:
|
||||
|
||||
```php
|
||||
use Filament\Forms\Components\Field;
|
||||
|
||||
class RangeSlider extends Field
|
||||
{
|
||||
protected string $view = 'filament.forms.components.range-slider';
|
||||
}
|
||||
```
|
||||
|
||||
It will also create a view file at `resources/views/filament/forms/components/range-slider.blade.php`.
|
||||
|
||||
## How fields work
|
||||
|
||||
Livewire components are PHP classes that have their state stored in the user's browser. When a network request is made, the state is sent to the server, and filled into public properties on the Livewire component class, where it can be accessed in the same way as any other class property in PHP can be.
|
||||
|
||||
Imagine you had a Livewire component with a public property called `$name`. You could bind that property to an input field in the HTML of the Livewire component in one of two ways: with the [`wire:model` attribute](https://livewire.laravel.com/docs/properties#data-binding), or by [entangling](https://livewire.laravel.com/docs/javascript#the-wire-object) it with an Alpine.js property:
|
||||
|
||||
```blade
|
||||
<input wire:model="name" />
|
||||
|
||||
<!-- Or -->
|
||||
|
||||
<div x-data="{ state: $wire.$entangle('name') }">
|
||||
<input x-model="state" />
|
||||
</div>
|
||||
```
|
||||
|
||||
When the user types into the input field, the `$name` property is updated in the Livewire component class. When the user submits the form, the `$name` property is sent to the server, where it can be saved.
|
||||
|
||||
This is the basis of how fields work in Filament. Each field is assigned to a public property in the Livewire component class, which is where the state of the field is stored. We call the name of this property the "state path" of the field. You can access the state path of a field using the `$getStatePath()` function in the field's view:
|
||||
|
||||
```blade
|
||||
<input wire:model="{{ $getStatePath() }}" />
|
||||
|
||||
<!-- Or -->
|
||||
|
||||
<div x-data="{ state: $wire.$entangle('{{ $getStatePath() }}') }">
|
||||
<input x-model="state" />
|
||||
</div>
|
||||
```
|
||||
|
||||
If your component heavily relies on third party libraries, we advise that you asynchronously load the Alpine.js component using the Filament asset system. This ensures that the Alpine.js component is only loaded when it's needed, and not on every page load. To find out how to do this, check out our [Assets documentation](../../support/assets#asynchronous-alpinejs-components).
|
||||
|
||||
## Rendering the field wrapper
|
||||
|
||||
Filament includes a "field wrapper" component, which is able to render the field's label, validation errors, and any other text surrounding the field. You may render the field wrapper like this in the view:
|
||||
|
||||
```blade
|
||||
<x-dynamic-component
|
||||
:component="$getFieldWrapperView()"
|
||||
:field="$field"
|
||||
>
|
||||
<!-- Field -->
|
||||
</x-dynamic-component>
|
||||
```
|
||||
|
||||
It's encouraged to use the field wrapper component whenever appropriate, as it will ensure that the field's design is consistent with the rest of the form.
|
||||
|
||||
## Accessing the Eloquent record
|
||||
|
||||
Inside your view, you may access the Eloquent record using the `$getRecord()` function:
|
||||
|
||||
```blade
|
||||
<div>
|
||||
{{ $getRecord()->name }}
|
||||
</div>
|
||||
```
|
||||
|
||||
## Obeying state binding modifiers
|
||||
|
||||
When you bind a field to a state path, you may use the `defer` modifier to ensure that the state is only sent to the server when the user submits the form, or whenever the next Livewire request is made. This is the default behavior.
|
||||
|
||||
However, you may use the [`live()`](../advanced#the-basics-of-reactivity) on a field to ensure that the state is sent to the server immediately when the user interacts with the field. This allows for lots of advanced use cases as explained in the [advanced](../advanced) section of the documentation.
|
||||
|
||||
Filament provides a `$applyStateBindingModifiers()` function that you may use in your view to apply any state binding modifiers to a `wire:model` or `$wire.$entangle()` binding:
|
||||
|
||||
```blade
|
||||
<input {{ $applyStateBindingModifiers('wire:model') }}="{{ $getStatePath() }}" />
|
||||
|
||||
<!-- Or -->
|
||||
|
||||
<div x-data="{ state: $wire.{{ $applyStateBindingModifiers("\$entangle('{$getStatePath()}')") }} }">
|
||||
<input x-model="state" />
|
||||
</div>
|
||||
```
|
||||
Reference in New Issue
Block a user