Custom form field

I need to update the product variants for a single product. To accomplish this, I've created a SlideOver Modal with custom field(ProductVariant::make('productId')) for the product variants. How can I get and update all the product variant data?
<?php
Tables\Actions\Action::make("product-variant-modal")->label('Variant')
->modalHeading("product")
->slideOver()
->form([
ProductVariant::make('productId'),
])
->modalDescription("Product description")
->action(function (array $data): void {
dd($data);
}),
<?php
Tables\Actions\Action::make("product-variant-modal")->label('Variant')
->modalHeading("product")
->slideOver()
->form([
ProductVariant::make('productId'),
])
->modalDescription("Product description")
->action(function (array $data): void {
dd($data);
}),
<?php
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
<?php
$customDecorations = \App\Models\CustomDecoration::all()->pluck('decoration', 'decoration');
?>
<div x-data="{ state: $wire.$entangle('{{ $getStatePath() }}') }">
@forelse($getRecord()->variants as $productVariant)
<div class="rounded-lg">
<div class="min_height flex">
<input type="checkbox" class="mt-6 fi-checkbox-input">
<label class="text-xs mt-6 ms-1" >{{ $productVariant->description }}</label>
</div>
<select class=" text-xs bg-gray-50 mt-1">
<option class="text-xs" value="">Please Select</option>
@foreach($customDecorations as $customDecoration)
<option class="text-xs" value="{{ $customDecoration }}">{{ $customDecoration }}</option>
@endforeach
</select>
</div>
@empty
<span class="col-span-full text-xs">No product variant found.</span>
@endforelse
</div>
</x-dynamic-component>
<?php
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
<?php
$customDecorations = \App\Models\CustomDecoration::all()->pluck('decoration', 'decoration');
?>
<div x-data="{ state: $wire.$entangle('{{ $getStatePath() }}') }">
@forelse($getRecord()->variants as $productVariant)
<div class="rounded-lg">
<div class="min_height flex">
<input type="checkbox" class="mt-6 fi-checkbox-input">
<label class="text-xs mt-6 ms-1" >{{ $productVariant->description }}</label>
</div>
<select class=" text-xs bg-gray-50 mt-1">
<option class="text-xs" value="">Please Select</option>
@foreach($customDecorations as $customDecoration)
<option class="text-xs" value="{{ $customDecoration }}">{{ $customDecoration }}</option>
@endforeach
</select>
</div>
@empty
<span class="col-span-full text-xs">No product variant found.</span>
@endforelse
</div>
</x-dynamic-component>
No description
No description
No description
Solution:
Thank you very much, Leandro Ferreira, Toeknee, and Awcodes. I have finally resolved it. I have just make a custom rule for it . ```<?php ->form([ Repeater::make('variants')...
Jump to solution
11 Replies
LeandroFerreira
LeandroFerreira6mo ago
If you are using a relationship, I think you could use a repeater. Something like this
Action::make('productVariantModal')
->record(fn ($record) => $record)
->fillForm(fn ($record) => $record->attributesToArray())
->form([
Repeater::make('variants')
->relationship('variants')
->schema([
Checkbox::make('description'),
Select::make('decoration_id')
...
])
])
Action::make('productVariantModal')
->record(fn ($record) => $record)
->fillForm(fn ($record) => $record->attributesToArray())
->form([
Repeater::make('variants')
->relationship('variants')
->schema([
Checkbox::make('description'),
Select::make('decoration_id')
...
])
])
Sourabh
SourabhOP6mo ago
I appreciate all of your helpful assistance. How can I send a message of success? , as well as how to modify the validation message Could you please assist me with this? I have try below code .
<?php
Tables\Actions\Action::make("product-variant-modal")
->tooltip('Update Decoration')
->icon('heroicon-o-pencil-square')
->iconButton()
->modalHeading("Product")
->slideOver()
->fillForm(fn ($record) => $record->attributesToArray())
->form([
Repeater::make('variants')
->relationship('variants')
->addable(false)
->deletable(false)
->grid(3)
->schema([
Checkbox::make('is_approved')
->live()
->label(fn($record) => $record->description ?? null),
Select::make('magento_type')
->label('Magento Decoration')
->required(fn (Get $get): bool => $get('is_approved'))
->validationMessages(['magento_type.required'=>"Please select magento decoration."])
->options(CustomDecoration::all()->pluck('decoration', 'decoration')),
])->afterStateUpdated(function (){
Notification::make()
->success()
->title('Decorations updated successfully')
->duration(3000)
->send();
})
]),
<?php
Tables\Actions\Action::make("product-variant-modal")
->tooltip('Update Decoration')
->icon('heroicon-o-pencil-square')
->iconButton()
->modalHeading("Product")
->slideOver()
->fillForm(fn ($record) => $record->attributesToArray())
->form([
Repeater::make('variants')
->relationship('variants')
->addable(false)
->deletable(false)
->grid(3)
->schema([
Checkbox::make('is_approved')
->live()
->label(fn($record) => $record->description ?? null),
Select::make('magento_type')
->label('Magento Decoration')
->required(fn (Get $get): bool => $get('is_approved'))
->validationMessages(['magento_type.required'=>"Please select magento decoration."])
->options(CustomDecoration::all()->pluck('decoration', 'decoration')),
])->afterStateUpdated(function (){
Notification::make()
->success()
->title('Decorations updated successfully')
->duration(3000)
->send();
})
]),
No description
LeandroFerreira
LeandroFerreira6mo ago
Action::make("product-variant-modal")
...
->after(function(){
//Notification..
})
Action::make("product-variant-modal")
...
->after(function(){
//Notification..
})
?
Sourabh
SourabhOP6mo ago
Thanks , you are correct .
Sourabh
SourabhOP6mo ago
Now, I want the form to be submitted only if at least one checkbox is checked; otherwise, a notification should display saying, "At least one variant must be checked." So is there any method like ->beforeCreate(function($data) {}) where i get all the data of the form? Can you please help me for the same .
No description
Sourabh
SourabhOP6mo ago
Is it possible to retrieve all form data before it is submitted, formatted as shown below?
<?php
$array = [
[
'is_approved' => false,
'id' => 5336,
'product_id' => 1427,
'magento_type' => 'Full Colour Transfer Print',
],
[
'is_approved' => false,
'id' => 5338,
'product_id' => 1427,
'magento_type' => 'Full Colour Transfer Print',
],
[
'is_approved' => false,
'id' => 57146,
'product_id' => 1427,
'magento_type' => 'Moulded PVC',
],
[
'is_approved' => false,
'id' => 100247,
'product_id' => 1427,
'magento_type' => NULL,
],
];
?>
<?php
$array = [
[
'is_approved' => false,
'id' => 5336,
'product_id' => 1427,
'magento_type' => 'Full Colour Transfer Print',
],
[
'is_approved' => false,
'id' => 5338,
'product_id' => 1427,
'magento_type' => 'Full Colour Transfer Print',
],
[
'is_approved' => false,
'id' => 57146,
'product_id' => 1427,
'magento_type' => 'Moulded PVC',
],
[
'is_approved' => false,
'id' => 100247,
'product_id' => 1427,
'magento_type' => NULL,
],
];
?>
I want to check if all checkboxes are unchecked, meaning is_approved is false for all items. If so, prevent the form from submitting and display a validation error: "At least one variant should be checked."
<?php
->beforeCreate(function(array $data) {

$atLeastOneVariantChecked = false;

foreach ($data as $variant) {
if ($variant['is_approved']) {
$atLeastOneVariantChecked = true;
}
}

if (!$atLeastOneVariantChecked) {
Notification::make()
->body('At least one variant should be checked.')
->send();
}
});
?>
<?php
->beforeCreate(function(array $data) {

$atLeastOneVariantChecked = false;

foreach ($data as $variant) {
if ($variant['is_approved']) {
$atLeastOneVariantChecked = true;
}
}

if (!$atLeastOneVariantChecked) {
Notification::make()
->body('At least one variant should be checked.')
->send();
}
});
?>
awcodes
awcodes6mo ago
I would think an empty array would fail the validation.
Sourabh
SourabhOP6mo ago
Thank you for both responses. How do I apply this in Repeater? like below code
<?php
public function updateVariants(Request $request)
{
$validator = Validator::make($request->only('Variants'), [
'Variants' => 'required|array',
'Variants.*.is_approved' => 'boolean',
]);

// Check if at least one variant is approved
$validator->after(function ($validator) use ($productVariants) {
$atLeastOneVariantChecked = false;
foreach ($productVariants as $variant) {
if ($variant['is_approved']) {
$atLeastOneVariantChecked = true;
}
}
if (! $atLeastOneVariantChecked) {
$validator->errors()->add('is_approved', 'At least one variant must be checked.');
}
});

// If validation fails, return the errors
if ($validator->fails()) {
return response()->json(['errors' => $validator->errors()], 422);
}
}
<?php
public function updateVariants(Request $request)
{
$validator = Validator::make($request->only('Variants'), [
'Variants' => 'required|array',
'Variants.*.is_approved' => 'boolean',
]);

// Check if at least one variant is approved
$validator->after(function ($validator) use ($productVariants) {
$atLeastOneVariantChecked = false;
foreach ($productVariants as $variant) {
if ($variant['is_approved']) {
$atLeastOneVariantChecked = true;
}
}
if (! $atLeastOneVariantChecked) {
$validator->errors()->add('is_approved', 'At least one variant must be checked.');
}
});

// If validation fails, return the errors
if ($validator->fails()) {
return response()->json(['errors' => $validator->errors()], 422);
}
}
I have attached the filament code as well for your reference .
<?php
Tables\Actions\Action::make("product-variant-modal")
->tooltip('Update Decoration')
->icon('heroicon-o-pencil-square')
->iconButton()
->modalHeading("Product")
->slideOver()
->record(fn ($record) => $record)
->fillForm(fn ($record) => $record->attributesToArray())
->form([
Repeater::make('variants')
->relationship('variants')
->addable(false)
->deletable(false)
->grid(3)
->schema([
Checkbox::make('is_approved')
->live()
->label(fn($record) => $record->description ?? null),
Hidden::make('id'),
Hidden::make('product_id'),
Select::make('magento_type')
->label('Magento Decoration')
->required(fn (Get $get): bool => $get('is_approved'))
->options(CustomDecoration::all()->pluck('decoration', 'decoration')),
])
->minItems(1)
->mutateRelationshipDataBeforeSaveUsing(function (array $data): ?array {
//Some code
])
->after(function (Product $record, ProductsServiceMagento $productsServiceMagento){
//Some code & notification
}),
<?php
Tables\Actions\Action::make("product-variant-modal")
->tooltip('Update Decoration')
->icon('heroicon-o-pencil-square')
->iconButton()
->modalHeading("Product")
->slideOver()
->record(fn ($record) => $record)
->fillForm(fn ($record) => $record->attributesToArray())
->form([
Repeater::make('variants')
->relationship('variants')
->addable(false)
->deletable(false)
->grid(3)
->schema([
Checkbox::make('is_approved')
->live()
->label(fn($record) => $record->description ?? null),
Hidden::make('id'),
Hidden::make('product_id'),
Select::make('magento_type')
->label('Magento Decoration')
->required(fn (Get $get): bool => $get('is_approved'))
->options(CustomDecoration::all()->pluck('decoration', 'decoration')),
])
->minItems(1)
->mutateRelationshipDataBeforeSaveUsing(function (array $data): ?array {
//Some code
])
->after(function (Product $record, ProductsServiceMagento $productsServiceMagento){
//Some code & notification
}),
Solution
Sourabh
Sourabh6mo ago
Thank you very much, Leandro Ferreira, Toeknee, and Awcodes. I have finally resolved it. I have just make a custom rule for it .
<?php
->form([
Repeater::make('variants')
->relationship('variants')
->schema([
Checkbox::make('is_approved'),
Select::make('decoration_id')
...
])
])->rules([new AtLeastOneVariantChecked])
<?php
->form([
Repeater::make('variants')
->relationship('variants')
->schema([
Checkbox::make('is_approved'),
Select::make('decoration_id')
...
])
])->rules([new AtLeastOneVariantChecked])
<?php
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$atLeastOneVariantChecked = collect($value)->where('is_approved', true)->isNotEmpty();
if ($atLeastOneVariantChecked === false) {
$fail('');
Notification::make()
->danger()
->title('At least one variant must be checked.')
->send();
}
}
<?php
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$atLeastOneVariantChecked = collect($value)->where('is_approved', true)->isNotEmpty();
if ($atLeastOneVariantChecked === false) {
$fail('');
Notification::make()
->danger()
->title('At least one variant must be checked.')
->send();
}
}
Want results from more Discord servers?
Add your server