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