Skip to content

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:

  1. Defining the UI for configuring the block in the form builder
  2. Converting the block configuration to a form field for survey respondents
  3. Converting the block configuration to a table column for displaying responses
  4. 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 UI
  • toField(Fluent $data): Converts the block data to a Filament Field for form rendering
  • toColumn(Fluent $data): Converts the block data to a Filament Column for table rendering
  • getSort(): Returns the sort order of the block
  • setSort(int $sort): Sets the sort order of the block
  • getId(): 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(), and getId()
  • Helper methods for creating common sections in the block builder UI:
    • getQuestionInformationSection(): Creates a section for question details
    • getValidationSection(): Creates a section for validation rules
  • Helper methods for placeholders and validation:
    • getQuestionPlaceholder(), getInputPlaceholder(): Default placeholders for questions and inputs
    • getMinLengthPlaceholder(), getMaxLengthPlaceholder(): Default placeholders for min/max length fields
    • makeId(): 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 field
    • hasCharacterValidation(): Whether this block type should display character validation fields
    • getCustomValidationFields(): 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 class
  • registerPath(): Registers all block classes in a directory
  • getAll(): Gets all registered blocks
  • getAllToBuilder(): Converts all blocks to Filament Builder Blocks for the builder UI
  • getAllToForm(): Converts blocks to Filament Fields for form rendering
  • getAllToTable(): Converts blocks to Filament Columns for table rendering
  • getAllToChart(): 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:

  1. Text Input Blocks:

    • ShortAnswerBlock: For short text responses
    • LongAnswerBlock: For longer text responses
    • RichTextAnswerBlock: For formatted text responses
  2. Choice Blocks:

    • CheckboxBlock: For multiple-choice questions (select multiple)
    • RadioBlock: For single-choice questions (select one)
    • SelectBlock: For dropdown selection questions
    • ToggleBlock: For yes/no questions
  3. Date and Time Blocks:

    • DateBlock: For date selection
    • TimeBlock: For time selection
    • DateTimeBlock: For date and time selection
    • DateRangeBlock: For date range selection
  4. Special Blocks:

    • FileUploadBlock: For file uploads
    • RatingBlock: For star ratings
    • ColorPickerBlock: For color selection
    • SeparatorBlock: For adding separators between questions
    • TextBlock: For adding static text