Bind different model to action form

I've created action with form that I am calling from some resource edit page. Model binded to that action form is the model that belongs to the resource from which I am calling that action. What I want is to bind completely different model to that action form that have no relation to underlying model. Any ideas how to do that. Example what I would like to do:
Filament\Forms\Components\Actions\Action::make('new_product')
// I know there is no setModel() method on action
->setModel(Product::class)
->form([
TextInput::make('product_name')->required(),
Select::make('product_type_id')
->relationship(name: 'type', titleAttribute: 'name')
])
->action(function () {
// When action is executed I want to create new product
});
Filament\Forms\Components\Actions\Action::make('new_product')
// I know there is no setModel() method on action
->setModel(Product::class)
->form([
TextInput::make('product_name')->required(),
Select::make('product_type_id')
->relationship(name: 'type', titleAttribute: 'name')
])
->action(function () {
// When action is executed I want to create new product
});
And that action button is called from PageResource edit page that is why I am creating Filament\Components\Actions\Action. My form in action is in no relation to a underlying Page model, and I want to be bind to Product model.
7 Replies
tjodalv
tjodalv8mo ago
I did found a solution to my problem but only partially. In my Page resource edit page I've added ViewField component that includes my custom Livewire component that contain CreateAction button to create new product. I've managed to do that, to render the button properly but when I click on it nothing happens. I expect to open modal form.
// app/Filament/Resources/PageResource.php
public static function form(Form $form)
{
return [
// ..other fields
Forms\Components\ViewField::make('create-product')
->view('filament.components.create-product-button'),
];
}
// app/Filament/Resources/PageResource.php
public static function form(Form $form)
{
return [
// ..other fields
Forms\Components\ViewField::make('create-product')
->view('filament.components.create-product-button'),
];
}
In ViewField blade template I am just rendering my custom Livewire component:
// resources/filament/components/create-product-button.blade.php
<livewire:create-product />
// resources/filament/components/create-product-button.blade.php
<livewire:create-product />
This is my custom Livewire component that has CreateAction button:
class CreateProduct extends Component implements HasForms, HasActions
{
use InteractsWithForms;
use InteractsWithActions;

public function createProduct(): Action
{
return CreateAction::make('new-product')
->model(Product::class)
->form([
// form fields here
]);
}

public function render()
{
return view('livewire.create-product');
}
}
class CreateProduct extends Component implements HasForms, HasActions
{
use InteractsWithForms;
use InteractsWithActions;

public function createProduct(): Action
{
return CreateAction::make('new-product')
->model(Product::class)
->form([
// form fields here
]);
}

public function render()
{
return view('livewire.create-product');
}
}
And livewire component template:
// resources/views/livewire/create-product.blade.php
<div>
{{ $this->createProduct() }}

<x-filament-actions::modals />
</div>
// resources/views/livewire/create-product.blade.php
<div>
{{ $this->createProduct() }}

<x-filament-actions::modals />
</div>
Why when clicking on the button, modal window with form is not opening? Can someone help me with this one?
Hiz
Hiz8mo ago
Maybe you can try this:
//CreateProduct.php

public function createProduct(array $data): void
{
Product::create([
'name' => $data['product_name'],
'type' => $data['product_type_id']
]);
}

protected function getHeaderActions(): array
{
return [
Action::make('newProduct')
->label('Create product')
->action(fn($data) => $this->createProduct($data))
->form([
TextInput::make('product_name')->required(),
Select::make('product_type_id')
->relationship(name: 'type', titleAttribute: 'name')
]),
];
}
//CreateProduct.php

public function createProduct(array $data): void
{
Product::create([
'name' => $data['product_name'],
'type' => $data['product_type_id']
]);
}

protected function getHeaderActions(): array
{
return [
Action::make('newProduct')
->label('Create product')
->action(fn($data) => $this->createProduct($data))
->form([
TextInput::make('product_name')->required(),
Select::make('product_type_id')
->relationship(name: 'type', titleAttribute: 'name')
]),
];
}
tjodalv
tjodalv8mo ago
The thing is that my Product has a lot of relationship fields that I need to handle, that is why I need CreateAction as that would handle all of the nested relationships. And I would like to position button for creating a new product inside form that, so that is why I am using custom Livewire component. The CreateAction button is rendering properly on the page, but when I click on it spinner appear and then disappear and that's it.
toeknee
toeknee8mo ago
Move the action below the form in the action order
tjodalv
tjodalv8mo ago
I am not sure I understand what I need to do?
toeknee
toeknee8mo ago
//CreateProduct.php

public function createProduct(array $data): void
{
Product::create([
'name' => $data['product_name'],
'type' => $data['product_type_id']
]);
}

protected function getHeaderActions(): array
{
return [
Action::make('newProduct')
->label('Create product')
->form([
TextInput::make('product_name')->required(),
Select::make('product_type_id')
->relationship(name: 'type', titleAttribute: 'name')
])
->action(fn($data) => $this->createProduct($data)),
];
}
//CreateProduct.php

public function createProduct(array $data): void
{
Product::create([
'name' => $data['product_name'],
'type' => $data['product_type_id']
]);
}

protected function getHeaderActions(): array
{
return [
Action::make('newProduct')
->label('Create product')
->form([
TextInput::make('product_name')->required(),
Select::make('product_type_id')
->relationship(name: 'type', titleAttribute: 'name')
])
->action(fn($data) => $this->createProduct($data)),
];
}
Try the above
tjodalv
tjodalv8mo ago
Can you explain in your example what is CreateProduct.php? In my scenario I want to use CreateAction to create Product in the PageResource. That is what I want to achieve. I want to open modal for creating Product from PageResource. I would like to implement that button inside PageResource edit form. I will try to put that Action in the header if it is not possible to add it inside the form. In my example CreateProduct.php is custom livewire component that I am calling in Filament\Forms\ViewField component in the PageResource form