Closed ryanmitchell closed 3 months ago
we do have "Dynamic Textbox" with bolt pro: https://demo.larazeus.com/bolt/bolt-pro
but it only have one field, I may add the repeater later this year to bolt pro
also you can add any field you want: https://larazeus.com/docs/bolt/v3/advanced/add-fields
Yeah I did see that, but as you said it's only one field, whereas we would want multiple fields to be repeatable.
I looked into making a custom field, but as the options then require sub options I couldn't see a way of doing it.
its doable:
<?php
namespace LaraZeus\BoltPro\Fields;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\TextInput;
use Filament\Tables\Columns\Column;
use Filament\Tables\Columns\TextColumn;
use LaraZeus\Accordion\Forms\Accordion;
use LaraZeus\Accordion\Forms\Accordions;
use LaraZeus\Bolt\Facades\Bolt;
use LaraZeus\Bolt\Fields\FieldsContract;
use LaraZeus\Bolt\Models\Field;
use LaraZeus\Bolt\Models\FieldResponse;
use LaraZeus\Bolt\Models\Response;
class Repeater extends FieldsContract
{
public string $renderClass = \Filament\Forms\Components\Repeater::class;
public int $sort = 103;
public function title(): string
{
return __('Dynamic Textbox');
}
public function icon(): string
{
return 'tabler-text-wrap';
}
public function description(): string
{
return __('add multiple text values');
}
public static function getOptions(): array
{
return [
Accordions::make('check-list-options')
->columns()
->accordions([
Accordion::make('general-options')
->label(__('General Options'))
->icon('iconpark-checklist-o')
->schema([
// add a repeater to defined the fields
TextInput::make('options.minItems')->default(1)->numeric(),
TextInput::make('options.maxItems')->default(1)->numeric(),
TextInput::make('options.defaultItems')->default(1)->numeric(),
self::required(),
self::htmlID(),
]),
]),
];
}
public static function getOptionsHidden(): array
{
return [
self::hiddenHtmlID(),
self::hiddenRequired(),
Hidden::make('options.minItems'),
Hidden::make('options.maxItems'),
Hidden::make('options.defaultItems'),
];
}
// @phpstan-ignore-next-line
public function appendFilamentComponentsOptions($component, $zeusField, bool $hasVisibility = false)
{
parent::appendFilamentComponentsOptions($component, $zeusField, $hasVisibility);
$fieldOptions = $zeusField['options'];
if (filled($fieldOptions['minItems'])) {
$component->minItems($fieldOptions['minItems']);
}
// render the repeater here with the schema from the fields in the $fieldOptions
if (filled($fieldOptions['maxItems'])) {
$component->maxItems($fieldOptions['maxItems']);
}
if (filled($fieldOptions['defaultItems'])) {
$component->defaultItems($fieldOptions['defaultItems']);
}
$repeatedField = TextInput::make('title');
if (filled($fieldOptions['is_required'])) {
$repeatedField->required()->default('');
}
$component
->simple($repeatedField)
->reorderableWithDragAndDrop(false)
->reorderableWithButtons()
->cloneable()
->addActionLabel(__('Add'))
->default(['']);
return $component;
}
public function getResponse(Field $field, FieldResponse $resp): string
{
$responseValue = (filled($resp->response) && Bolt::isJson($resp->response)) ? json_decode($resp->response) : [$resp->response];
return view('zeus::filament.fields.repeater')
->with('resp', $resp)
->with('responseValue', $responseValue)
->with('field', $field)
->render();
}
public function TableColumn(Field $field): ?Column
{
return TextColumn::make('zeusData.' . $field->id)
->label($field->name)
->badge()
->getStateUsing(function (Response $record) use ($field) {
return json_decode($record->fieldsResponses->where('field_id', $field->id)->first()->response);
})
->toggleable();
}
}
this is the simple repeater code and you can adjust it to be with multiple.
remember all the entries of the form (repeater or not) will be stored in one row in the responses
table
so keep in mind the performance I recommend not to do it like this and go with separate models you can also use the extensions https://larazeus.com/docs/bolt/v3/advanced/extension
Thanks for sharing the code. Yes that sets the min/max, but it doesn't let you define the schema of the repeating block per form, which is where I've been struggling.
Using an extension wont work in this instance as the repeating fields need to be user definable.
did you see the comment
// add a repeater to defined the fields
you can render a repeater here as per filament docs and it will be saved to the db then
// render the repeater here with the schema from the fields in the $fieldOptions
to render the saved items in another repeater read the code and try to understand it how it works, since I dont think I am gonna add the repeater till after the summer/early winter.
Sorry, yeah I see what you mean now. Ok - I'll see how we get on with that.
feel free to comment or reopen if more assistant needed :)
Is your feature request related to a problem? Please describe. We are looking to build forms where you can have multiple participants, each with a name, email and other user defined fields. Currently I can't see a way to achieve this.
Describe the solution you'd like I would like to be able to use the Repeater field from core (with min/max options etc) to allow me to add multiple participants to my form submission.
Describe alternatives you've considered An alternative would be to allow sections to be multi-filled, again with min and max options.