mirror of
https://github.com/filamentphp/filament.git
synced 2026-10-30 18:42:45 +08:00
wip
This commit is contained in:
@@ -49,9 +49,14 @@ class EditPost extends Component implements Forms\Contracts\HasForms
|
||||
{
|
||||
use Forms\Concerns\InteractsWithForms;
|
||||
|
||||
public $title = '';
|
||||
public $content = '';
|
||||
|
||||
protected function getFormSchema(): array // [tl! add:start]
|
||||
{
|
||||
return [
|
||||
Forms\Components\TextInput::make('title')->required(),
|
||||
Forms\Components\MarkdownEditor::make('content'),
|
||||
// ...
|
||||
];
|
||||
} // [tl! add:end]
|
||||
@@ -89,12 +94,12 @@ class EditPost extends Component implements Forms\Contracts\HasForms
|
||||
|
||||
public Post $post;
|
||||
|
||||
public $title;
|
||||
public $content;
|
||||
public $title = '';
|
||||
public $content = '';
|
||||
|
||||
public function mount(): void // [tl! add:start]
|
||||
{
|
||||
$this->fill([
|
||||
$this->form->fill([
|
||||
'title' => $this->post->title,
|
||||
'content' => $this->post->content,
|
||||
]);
|
||||
@@ -103,7 +108,7 @@ class EditPost extends Component implements Forms\Contracts\HasForms
|
||||
protected function getFormSchema(): array
|
||||
{
|
||||
return [
|
||||
Forms\Components\TextInput::make('title'),
|
||||
Forms\Components\TextInput::make('title')->required(),
|
||||
Forms\Components\MarkdownEditor::make('content'),
|
||||
];
|
||||
}
|
||||
@@ -135,19 +140,20 @@ class CreatePost extends Component implements Forms\Contracts\HasForms
|
||||
{
|
||||
use Forms\Concerns\InteractsWithForms;
|
||||
|
||||
public $title;
|
||||
public $content;
|
||||
public $title = '';
|
||||
public $content = '';
|
||||
|
||||
public function mount(): void // [tl! add:start]
|
||||
{
|
||||
$this->fill();
|
||||
$this->form->fill();
|
||||
} // [tl! add:end]
|
||||
|
||||
protected function getFormSchema(): array
|
||||
{
|
||||
return [
|
||||
Forms\Components\TextInput::make('title')
|
||||
->default('Status Update'), // [tl! add:start]
|
||||
->default('Status Update') // [tl! add]
|
||||
->required(),
|
||||
Forms\Components\MarkdownEditor::make('content'),
|
||||
];
|
||||
}
|
||||
@@ -159,10 +165,274 @@ class CreatePost extends Component implements Forms\Contracts\HasForms
|
||||
}
|
||||
```
|
||||
|
||||
## Validation
|
||||
## Getting data from forms
|
||||
|
||||
$this->form->getState()
|
||||
To get all form data in an array, call the `getState()` method on your form.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Models\Post;
|
||||
use Filament\Forms;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Livewire\Component;
|
||||
|
||||
class CreatePost extends Component implements Forms\Contracts\HasForms
|
||||
{
|
||||
use Forms\Concerns\InteractsWithForms;
|
||||
|
||||
public $title = '';
|
||||
public $content = '';
|
||||
|
||||
protected function getFormSchema(): array
|
||||
{
|
||||
return [
|
||||
Forms\Components\TextInput::make('title')->required(),
|
||||
Forms\Components\MarkdownEditor::make('content'),
|
||||
];
|
||||
}
|
||||
|
||||
public function create(): void // [tl! add:start]
|
||||
{
|
||||
Post::create($this->form->getState());
|
||||
} // [tl! add:end]
|
||||
|
||||
public function render(): View
|
||||
{
|
||||
return view('create-post');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When `getState()` is run:
|
||||
|
||||
1) Validation rules are checked, and if errors are present, the form is not submitted.
|
||||
2) Any pending file uploads are stored permanently in the filesystem.
|
||||
3) [Field relationships](#working-with-field-relationships), if they are defined, are saved.
|
||||
|
||||
## Using Eloquent model binding
|
||||
|
||||
Using Eloquent model binding for fields works out of the box, using Livewire's dot-syntax:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Models\Post;
|
||||
use Filament\Forms;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Livewire\Component;
|
||||
|
||||
class EditPost extends Component implements Forms\Contracts\HasForms
|
||||
{
|
||||
use Forms\Concerns\InteractsWithForms;
|
||||
|
||||
public Post $post;
|
||||
|
||||
protected function getFormSchema(): array
|
||||
{
|
||||
return [
|
||||
Forms\Components\TextInput::make('post.title')->required(), // [tl! add:start]
|
||||
Forms\Components\MarkdownEditor::make('post.content'), // [tl! add:end]
|
||||
];
|
||||
}
|
||||
|
||||
public function render(): View
|
||||
{
|
||||
return view('edit-post');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Using multiple forms
|
||||
|
||||
getForms()
|
||||
By default, the `InteractsWithForms` trait only handles one form per Livewire component. To change this, you can override the `getForms()` method to return more than one form, each with a unique name:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Models\Author;
|
||||
use App\Models\Post;
|
||||
use Filament\Forms;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Livewire\Component;
|
||||
|
||||
class EditPost extends Component implements Forms\Contracts\HasForms
|
||||
{
|
||||
use Forms\Concerns\InteractsWithForms;
|
||||
|
||||
public Author $author;
|
||||
public Post $post;
|
||||
|
||||
protected function getPostFormSchema(): array
|
||||
{
|
||||
return [
|
||||
Forms\Components\TextInput::make('post.title')->required(),
|
||||
Forms\Components\MarkdownEditor::make('post.content'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function getAuthorFormSchema(): array
|
||||
{
|
||||
return [
|
||||
Forms\Components\TextInput::make('author.name')->required(),
|
||||
Forms\Components\TextInput::make('author.email')->email()->required(),
|
||||
];
|
||||
}
|
||||
|
||||
public function save(): void
|
||||
{
|
||||
$this->post->update(
|
||||
$this->postForm->getState(),
|
||||
);
|
||||
|
||||
$this->author->update(
|
||||
$this->authorForm->getState(),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getForms(): array // [tl! add:start]
|
||||
{
|
||||
return [
|
||||
'postForm' => $this->makeForm()->schema($this->getPostFormSchema()),
|
||||
'authorForm' => $this->makeForm()->schema($this->getAuthorFormSchema()),
|
||||
];
|
||||
} // [tl! add:end]
|
||||
|
||||
public function render(): View
|
||||
{
|
||||
return view('edit-post');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Working with field relationships
|
||||
|
||||
Some fields, such as the `BelongsToSelect`, `SpatieMediaLibraryFileUpload` and `SpatieLaravelTagsInput` require you to pass an Eloquent model instance to the form directly. This allows them to attach Eloquent relationships automatically when the form is saved.
|
||||
|
||||
Pass a model instance to a form using the `getFormModel()` method:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Models\Post;
|
||||
use Filament\Forms;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Livewire\Component;
|
||||
|
||||
class EditPost extends Component implements Forms\Contracts\HasForms
|
||||
{
|
||||
use Forms\Concerns\InteractsWithForms;
|
||||
|
||||
public Post $post;
|
||||
|
||||
protected function getFormSchema(): array
|
||||
{
|
||||
return [
|
||||
Forms\Components\TextInput::make('post.title')->required(),
|
||||
Forms\Components\MarkdownEditor::make('post.content'),
|
||||
Forms\Components\SpatieTagsInput::make('post.tags'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function getFormModel(): Post // [tl! add:start]
|
||||
{
|
||||
return $this->post;
|
||||
} // [tl! add:end]
|
||||
|
||||
public function render(): View
|
||||
{
|
||||
return view('edit-post');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, you may pass the model instance to the field that requires it directly, using the `model()` method:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Models\Post;
|
||||
use Filament\Forms;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Livewire\Component;
|
||||
|
||||
class EditPost extends Component implements Forms\Contracts\HasForms
|
||||
{
|
||||
use Forms\Concerns\InteractsWithForms;
|
||||
|
||||
public Post $post;
|
||||
|
||||
protected function getFormSchema(): array
|
||||
{
|
||||
return [
|
||||
Forms\Components\TextInput::make('post.title')->required(),
|
||||
Forms\Components\MarkdownEditor::make('post.content'),
|
||||
Forms\Components\SpatieTagsInput::make('post.tags')->model($this->post), // [tl! add]
|
||||
];
|
||||
}
|
||||
|
||||
public function render(): View
|
||||
{
|
||||
return view('edit-post');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now, [when `getState()` is called on this form](#getting-data-from-forms), any relationships are saved automatically to this model.
|
||||
|
||||
### Saving field relationships manually
|
||||
|
||||
In some cases, the model instance is not available until the form has been submitted. For example, in a form that creates a post, the post model instance cannot be passed to the form before it has been submitted.
|
||||
|
||||
In this situation, you may call the `model()` and `saveRelationships()` methods on the form after the instance has been created:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Models\Post;
|
||||
use Filament\Forms;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Livewire\Component;
|
||||
|
||||
class CreatePost extends Component implements Forms\Contracts\HasForms
|
||||
{
|
||||
use Forms\Concerns\InteractsWithForms;
|
||||
|
||||
public $title = '';
|
||||
public $content = '';
|
||||
public $tags = [];
|
||||
|
||||
protected function getFormSchema(): array
|
||||
{
|
||||
return [
|
||||
Forms\Components\TextInput::make('title')->required(),
|
||||
Forms\Components\MarkdownEditor::make('content'),
|
||||
Forms\Components\SpatieTagsInput::make('tags'),
|
||||
];
|
||||
}
|
||||
|
||||
public function create(): void
|
||||
{
|
||||
$post = Post::create($this->form->getState());
|
||||
|
||||
$this->form->model($post)->saveRelationships(); // [tl! add]
|
||||
}
|
||||
|
||||
public function render(): View
|
||||
{
|
||||
return view('create-post');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -8,7 +8,7 @@ trait BelongsToModel
|
||||
{
|
||||
protected $model = null;
|
||||
|
||||
public function model(Model | string | callable $model): static
|
||||
public function model(Model | string | callable | null $model = null): static
|
||||
{
|
||||
$this->model = $model;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ trait BelongsToModel
|
||||
public function saveRelationships(): void
|
||||
{
|
||||
foreach ($this->getComponents() as $component) {
|
||||
if ($component->getModel()) {
|
||||
if ($component->getModel() instanceof Model) {
|
||||
$component->saveRelationships();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Filament\Forms\Concerns;
|
||||
|
||||
use Filament\Forms\ComponentContainer;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Livewire\WithFileUploads;
|
||||
use SplFileInfo;
|
||||
@@ -176,6 +177,11 @@ trait InteractsWithForms
|
||||
return $this->cachedForms;
|
||||
}
|
||||
|
||||
protected function getFormModel(): Model | string | null
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function getFormSchema(): array
|
||||
{
|
||||
return [];
|
||||
@@ -184,7 +190,9 @@ trait InteractsWithForms
|
||||
protected function getForms(): array
|
||||
{
|
||||
return [
|
||||
'form' => $this->makeForm()->schema($this->getFormSchema()),
|
||||
'form' => $this->makeForm()
|
||||
->schema($this->getFormSchema())
|
||||
->model($this->getFormModel()),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user