#create records view. How add another custom button

55 messages · Page 1 of 1 (latest)

next sonnet
#

In my create product view, I want to add a custom button "Generate product variants", when my own custom function to handle that button click.
How can I do that?

lethal echoBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

vagrant swift
#

You'd need to overwrite the action (or use ->after()) and add an action via ->modalFooterActions()

next sonnet
#

Can you please share the documentation links for overwrite the action or ->after(). I am not sure which one it is

next sonnet
vagrant swift
next sonnet
keen urchin
next sonnet
keen urchin
#

I think $this->getCancelFormAction(),

vagrant swift
next sonnet
#

I finally got something like this

    /*
    $this->data 
    array:4 [
      "name" => "xxxx"
      "category_id" => "1"
      "thumbnail" => array:1 [▶]
      "variants_outline" => "yyyy"
    ]
    */

    protected function getFormActions(): array
    {
        return [
            Actions\Action::make('Generate Variants')->action('generateVariants'),
            Actions\Action::make('Save product')->action('save'),
            $this->getCancelFormAction(),
        ];
    }
    public function generateVariants(): void
    {
        print_r($this->data);
    }

Now in my generateVariants method, if one of the fields doesnt match a certain format, how can I return validation error?

keen urchin
#

I think that is just a validation on your form itself right?

next sonnet
#

What do you mean by "my form"?

Currently in the ProductResource

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\Components\Textarea::make('name')
                    ->required()
                    ->columnSpanFull(),
                Forms\Components\Select::make('category_id')
                    ->required()
                    ->relationship('category', 'name'),
                Forms\Components\FileUpload::make('thumbnail')
                    ->required()
                    ->image(),
                Forms\Components\Textarea::make('variants_outline')
                    ->hint('Please outline your product variations in the following format: size:small,large,extra_large;color:red,blue . If the product have no variations, then leave this empty.')
                    ->regex('/[A-Za-z0-9_]+:[A-Za-z0-9_]+(,[A-Za-z0-9_]+)+(;[A-Za-z0-9_]+:[A-Za-z0-9_]+(,[A-Za-z0-9_]+)+)+/i') // Todo: decide to have regex here or in CreateProduct
                    ->columnSpanFull(),

            ]);
#

if that answers your q

next sonnet
keen urchin
#

Can you tell a bit what you are exactly trying to acchieve with the function?

next sonnet
#

You know in a typical eCommerce website, when shopkeeper enters a new product (with variants) in the backoffice,
he enters the product name, desc...
then he write out the product variant's attributes and values,
then he clicks Generate Product Variants button,
then after the backend generates all the variants, the shopkeeper can go in and fill in all the skus, prices, images, ... for all the variants,
then he clicks save, and then the product and its variants are saved to the DB

#

That's my intention ^

#

Too much customization for Filament to handle?

#

Maybe I have to consider using beforeCreate and afterCreate again.
Shopkeeper can generate the variants and save product and variants in the create phase.
Then shopkeeper can then fill in the variant info in the edit phase.

So unless someone have a better idea, that's my plan B

vagrant swift
#

Have a look at the default save method and copy what you need

vagrant swift
next sonnet
next sonnet
#

Actually I cant find it.
The closest I found is this, which isnt much

    protected function getCreateFormAction(): Action
    {
        return Action::make('create')
            ->label(__('filament-panels::resources/pages/create-record.form.actions.create.label'))
            ->submit('create')
            ->keyBindings(['mod+s']);
    }
vagrant swift
next sonnet
#

A follow up Q pls. How can you do something like this?

dim scarab
# next sonnet
Textarea::make('variants_outline')
  ->live(debounce: 500)

CreatePage

protected function getCreateFormAction(): Action
{
    return parent::getCreateFormAction()
        ->disabled(fn () => blank($this->data['variants_outline']));
}
next sonnet
#

Very helpful. Thank you. But getCreateFormAction gets the default save button (wouldnt it?). The "Generate variants" button in my screenshot is a custom button (and event handler function) that I wrote, like this

    protected function getFormActions(): array
    {
        return [
            Actions\Action::make('Generate Variants')->action('generateVariants'),
            ...
        ];
    }
    public function generateVariants()
    {
        
    }
subtle smelt
#

Shouldn’t it be $this->generateVarients()? Unless the method is a registered action it won’t be available by name. So it needs to be an actual callback.

next sonnet
#

Not sure if I understood you correctly. But you mean I should disable the "Generate Variant" button in the public function generateVariants() method?
But how do I get a handle on the "Generate Variant" button? I cant use parent::getCreateFormAction() to grab the button

subtle smelt
#

Well, your code doesn’t show anything about the default create action? So not sure I can answer your question. Seems like you are trying to chain onto the create action when an observer / job would make more sense.

#

But you can override the default save action if you choose to do so. Just make sure you also handle the save logic implicitly.

next sonnet
# next sonnet

I am not using getCreateFormAction. Im not planning to use getCreateFormAction, because what Im planning to do is very custom. Both of the first 2 buttons are custom.

next sonnet
next sonnet
subtle smelt
#

You provide a callback function to the ->disabled() method.

#

The code you have been sharing doesn’t align to the questions you are asking. So it’s difficult for us to give you an answer.

subtle smelt
#

generateVariants isn't registered as an action so you can't call it by name.

->action($this->generateVariants())
next sonnet
#

So $this->action($this->generateVariants()) this is the only way to "get a handle" on my custom generate variants button?

subtle smelt
#

Did you try it? Does it even work?

next sonnet
#

Actually no. I looked at my code again. There is no place to put such codes. Im open to other ideas

keen urchin
#
protected function getFormActions(): array
{
    return [
        Actions\Action::make('Generate Variants')->action(
            self::generateVariants();
        ),
        ...
    ];
}
public static function generateVariants()
{

}

I think like this?

next sonnet
#

But on a positive note, I finally figured out where and how to disable custom buttons

    protected function getFormActions(): array
    {
        return [
            Actions\Action::make('Generate Variants')->action('generateVariants')->disabled(true),
next sonnet
#

In CreateProduct page, I did

    protected function getFormActions(): array
    {
        return [
            Actions\Action::make('Generate Variants')->action('generateVariants')->disabled(fn () => blank($this->data['variants_outline'])),

In the ProductResource I did

class ProductResource extends Resource
{
    protected static ?string $model = Product::class;

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\Components\Textarea::make('variants_outline')
                    ->live(debounce: 500),