Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for nested block validation #2638

Open
wants to merge 6 commits into
base: 3.x
Choose a base branch
from

Conversation

antonioribeiro
Copy link
Member

@antonioribeiro antonioribeiro commented Jul 26, 2024

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

@ifox
Copy link
Member

ifox commented Oct 14, 2024

Awesome @antonioribeiro. I'd like to merge this, but the tests are showing that this broke the blocks list command, as it is trying to render the new property you added here.

@CLAassistant
Copy link

CLAassistant commented Oct 15, 2024

CLA assistant check
All committers have signed the CLA.

@antonioribeiro antonioribeiro force-pushed the support-nested-blocks-validation branch from d0c5edd to 05f2865 Compare October 15, 2024 09:04
@antonioribeiro
Copy link
Member Author

Hey ifox, tests pass locally, but manually running the command did give me that error. I just removed the messages from the list, did some other testing here and it seems all good. Waiting for the tests to finishing running on Github

@antonioribeiro antonioribeiro force-pushed the support-nested-blocks-validation branch from 05f2865 to 3de13f4 Compare October 15, 2024 09:15
@antonioribeiro antonioribeiro force-pushed the support-nested-blocks-validation branch from 3de13f4 to f29cb91 Compare October 15, 2024 09:22
$finalValidator->getMessageBag()->add("blocks.$id" . "[$key][$locale]", $error);
$finalValidator->getMessageBag()->add("blocks.$locale", 'Failed');
}
}
}
}
foreach ($basicRules as $field => $rules) {
$validator = Validator::make([$field => $formData[$field] ?? null], [$field => $rules]);
$validator = Validator::make($formData, [$field => $rules], $messages);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't we just drop the foreach loop at this point and pass $basicRules directly to the validator?

I just ran into the same issue validating fields and media browsers within a repeater of a block, thought I couldn't be the first and found this PR, so thank you for that 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Block validation: Improve nested support
4 participants