Appearance
Creating Blocks
Overview
Blocks are the fundamental building blocks of the Survey module's form builder system. They represent reusable form components that can be used to create dynamic survey forms. Each block represents a specific type of question or form element (e.g., text input, checkbox list, radio buttons, etc.) that can be added to a survey.
The block system is designed to be extensible, allowing developers to create custom blocks to meet specific requirements. Blocks are responsible for:
- Defining the UI for configuring the block in the form builder
- Converting the block configuration to a form field for survey respondents
- Converting the block configuration to a table column for displaying responses
- Optionally generating charts for visualizing response data
Architecture
The block system is built on several key parts:
AsBlock Interface
The AsBlock
interface defines the contract that all blocks must implement. It includes the following methods:
toBuilder()
: Returns a Filament Builder Block instance for the block builder UItoField(Fluent $data)
: Converts the block data to a Filament Field for form renderingtoColumn(Fluent $data)
: Converts the block data to a Filament Column for table renderinggetSort()
: Returns the sort order of the blocksetSort(int $sort)
: Sets the sort order of the blockgetId()
: Returns the unique identifier of the block
BaseBlock Class
The BaseBlock
abstract class provides a base implementation of the AsBlock
interface with common functionality for all blocks:
- Default implementation for
getSort()
,setSort()
, andgetId()
- Helper methods for creating common sections in the block builder UI:
getQuestionInformationSection()
: Creates a section for question detailsgetValidationSection()
: Creates a section for validation rules
- Helper methods for placeholders and validation:
getQuestionPlaceholder()
,getInputPlaceholder()
: Default placeholders for questions and inputsgetMinLengthPlaceholder()
,getMaxLengthPlaceholder()
: Default placeholders for min/max length fieldsmakeId()
: Utility to create slug-based IDs from labels
- Configuration methods that can be overridden by child classes:
hasPlaceholder()
: Whether this block type should display a placeholder fieldhasCharacterValidation()
: Whether this block type should display character validation fieldsgetCustomValidationFields()
: Returns custom validation fields specific to this block type
BlocksManager
The BlocksManager
class is responsible for registering and managing blocks in the system:
register()
: Registers a single block classregisterPath()
: Registers all block classes in a directorygetAll()
: Gets all registered blocksgetAllToBuilder()
: Converts all blocks to Filament Builder Blocks for the builder UIgetAllToForm()
: Converts blocks to Filament Fields for form renderinggetAllToTable()
: Converts blocks to Filament Columns for table renderinggetAllToChart()
: Converts blocks to charts for data visualization (only for blocks that implement HasChart)
HasChart Interface
The HasChart
interface is an optional interface that blocks can implement to provide chart generation functionality:
toChart(Fluent $blockData, Survey $survey)
: Generates chart data for visualization
Creating a Custom Block
To create a custom block, you need to create a class that implements the AsBlock
interface. The easiest way to do this is to extend the BaseBlock
class provided by the Surveys module.
php
<?php
declare(strict_types = 1);
namespace YourNamespace\Blocks;
use Filament\Forms\Components\Builder\Block;
use Filament\Forms\Components\Field;
use Filament\Forms\Components\TextInput;
use Filament\Tables\Columns\Column;
use Filament\Tables\Columns\TextColumn;
use Illuminate\Support\Fluent;
use Modules\Surveys\Support\BaseBlock;
class YourCustomBlock extends BaseBlock
{
protected int $sort = 50; // Set the sort order for this block
public function toBuilder(): Block
{
return Block::make('your-custom-block')
->label(__('Your Custom Block'))
->icon('heroicon-o-document-text')
->schema([
$this->getQuestionInformationSection(),
$this->getValidationSection(),
// Add any additional sections specific to your block
])
->columns(1);
}
public function toField(Fluent $data): Field
{
return TextInput::make((string) $data->ulid)
->label($data->label)
->placeholder($data->placeholder ?? null)
->helperText($data->helper_text ?? null)
->required($data->required ?? false)
->when($data->min_length, fn (TextInput $field): TextInput => $field->minLength((int) $data->min_length))
->when($data->max_length, fn (TextInput $field): TextInput => $field->maxLength((int) $data->max_length));
}
public function toColumn(Fluent $data): Column
{
return TextColumn::make((string) $data->ulid)
->label($data->label ?? __('Response'))
->limit(50)
->placeholder('-');
}
// Override any BaseBlock methods as needed
protected function getQuestionPlaceholder(): string
{
return __('e.g., What is your custom question?');
}
protected function getInputPlaceholder(): string
{
return __('e.g., Type your custom answer here');
}
}
Registering Blocks
In your service provider's boot()
method:
php
use Modules\Surveys\Facades\Blocks;
use YourNamespace\Blocks\YourCustomBlock;
public function boot(): void
{
// Register a single block
Blocks::register(YourCustomBlock::class);
// Or register all blocks in a directory
Blocks::registerPath(module_path($this->nameLower, '/app/Blocks'));
}
Pre Built Blocks
The Surveys module includes built-in block types:
Text Input Blocks:
ShortAnswerBlock
: For short text responsesLongAnswerBlock
: For longer text responsesRichTextAnswerBlock
: For formatted text responses
Choice Blocks:
CheckboxBlock
: For multiple-choice questions (select multiple)RadioBlock
: For single-choice questions (select one)SelectBlock
: For dropdown selection questionsToggleBlock
: For yes/no questions
Date and Time Blocks:
DateBlock
: For date selectionTimeBlock
: For time selectionDateTimeBlock
: For date and time selectionDateRangeBlock
: For date range selection
Special Blocks:
FileUploadBlock
: For file uploadsRatingBlock
: For star ratingsColorPickerBlock
: For color selectionSeparatorBlock
: For adding separators between questionsTextBlock
: For adding static text