area17 / twill

Twill is an open source CMS toolkit for Laravel that helps developers rapidly create a custom admin console that is intuitive, powerful and flexible. Chat with us on Discord at https://discord.gg/cnWk7EFv8R.
https://twillcms.com
Apache License 2.0
3.72k stars 568 forks source link

Add support for nested block validation #2638

Open antonioribeiro opened 1 month ago

antonioribeiro commented 1 month ago

Description

Adds support not only to validate neste blocks, but also for custom messages, all to be set within the block.

Here's how it presents itself:

Screenshot 2024-07-26 at 17 08 43

Here's a full block example of it working:

<?php

namespace App\View\Components\Twill\Blocks;

use Illuminate\View\View;
use A17\Twill\Models\Block;
use Illuminate\Support\Str;
use A17\Twill\Services\Forms\Form;
use A17\Twill\Services\Forms\Fields\Input;
use A17\Twill\Services\Forms\Fields\Select;
use A17\Twill\Services\Forms\InlineRepeater;
use App\View\Components\Twill\Base\Block as TwillBlockComponent;

class CardsWithNumbers extends TwillBlockComponent
{
    const VIEW = 'site.blocks.cards-with-numbers';

    public function render(): View
    {
        return view(self::VIEW, $this->renderData());
    }

    public function prefix(): string
    {
        return Str::snake('CardsWithNumbers');
    }

    public function renderData(): array
    {
        return [
            'type' => $this->prefix(),

            'view' => self::VIEW,

            'sub_type' => $this->input('sub_type'),

            'section_title' => $this->input('section_title'),

            'cards' => $this->block->children
                ->map(function (Block $card) {
                    return [
                        'number' => $card->input('number'),

                        'title' => $card->input('title'),

                        'text' => $card->input('text'),

                        'micro_cards' => $card->children
                            ->map(function (Block $microCard) {
                                return [
                                    'text' => $microCard->input('text'),
                                ];
                            })
                            ->toArray(),
                    ];
                })
                ->toArray(),
        ];
    }

    public function getForm(): Form
    {
        return Form::make([
            Select::make()
                ->name('sub_type')
                ->label('Subtype')
                ->options([
                    'vertical' => 'Vertical',
                    'horizontal' => 'Horizontal',
                ]),

            Input::make()->name('section_title')->label('Section title'),

            InlineRepeater::make()
                ->name($this->prefix() . '_cards')
                ->label('Card')
                ->triggerText('Add a card')
                ->titleField('name')
                ->fields([
                    Input::make()->name('number')->maxLength(30),

                    Input::make()->name('title')->maxLength(50),

                    Input::make()->name('text')->type('textarea')->rows(4)->maxLength(300),

                    Input::make()->name('text_translated')->label('Text translatable')->type('textarea')->rows(4)->maxLength(300)->translatable(),

                    InlineRepeater::make()
                                  ->name($this->prefix() . '_micro_cards')
                                  ->label('Micro card')
                                  ->triggerText('Add a micro card')
                                  ->titleField('name')
                                  ->fields([
                                      Input::make()->name('text')->type('textarea')->rows(4)->maxLength(300),
                                  ]),

                ]),
        ]);
    }

    public static function getBlockIcon(): string
    {
        return 'b-carousel';
    }

    public static function getBlockTitle(): string
    {
        return 'Cards with number';
    }

    public function getValidationRules(): array
    {
        $rules = parent::getValidationRules();

        $rules['cards_with_numbers_cards.*.content.text'] = ['max:300'];
        $rules['cards_with_numbers_cards.*.blocks.cards_with_numbers_micro_cards.*.content.text'] = ['max:250'];

        return $rules;
    }

    public function getTranslatableValidationRules(): array
    {
        $rules = parent::getTranslatableValidationRules();

        $rules['cards_with_numbers_cards.*.content.text_translated'] = ['max:300'];

        return $rules;
    }

    public function getValidationMessages(): array
    {
        $messages = parent::getValidationMessages();

        $messages['cards_with_numbers_cards.*.content.text.max'] = 'The text may not be greater than 300 characters.';

        $messages['cards_with_numbers_cards.*.content.text_translated.*.max'] = 'The text may not be greater than 300 characters.';

        $messages['cards_with_numbers_cards.*.blocks.cards_with_numbers_micro_cards.*.content.text.max'] = 'The text may not be greater than 250 characters.';

        return $messages;
    }
}

Related Issues

Fixes #1850