Sections in Repeater Views


Why is it different than normal

Repeaters by default have an index for each instance of the form builder. If you declare the fields in your section definition, it won't actually match the fields once rendered. We will have a stream of cards which will hold our repeater data, the below example is from a pricing card block.

What we need

Scaffold out the stream as you normally would (php artisan make:stream cards namespace.addonType.addonName). You can use the default form builder created by the stub if you want to, however I like to have a dedicated RepeaterFormBuilder and RepeaterFormSections stored under Support/RepeaterFieldType, so we will use that in the example.

TLDR: Steps needed to complete the task:

  1. Update model to use the repeater form builder callback
  2. Update the form builder to reference our sections class
  3. Create the sections and add the prefixer method

Update your Model

The first thing you will need to do is update the model for the stream to use repeater field types callback so we can use our own custom builders. The nice thing about this is that we are then able to do all the normal form builder things that we would normally like to. Just remember that each instance in a repeater is its own unique copy of the form builder.

use Emange\PricingCardsBlockExtension\Card\Support\RepeaterFieldType\RepeaterFormBuilder;
use Emange\PricingCardsBlockExtension\Card\Contract\CardInterface;

class CardModel extends PricingCardsBlockCardsEntryModel implements CardInterface
{
    public function newRepeaterFieldTypeFormBuilder()
    {
        return app(RepeaterFormBuilder::class);
    }
}

Update your Form Builder

Point the sections to your sections class.

use Anomaly\Streams\Platform\Ui\Form\FormBuilder;
class RepeaterFormBuilder extends FormBuilder
{

    /**
     * The form sections.
     *
     * @var array
     */
    protected $sections = RepeaterFormSections::class;

}

Add the sections to your Sections Class

Add the sections as you normally would in any form builder.

  /**
     * Handle the sections.
     *
     * @param RepeaterFormBuilder $builder
     * @param Request $request
     */
    public function handle(RepeaterFormBuilder $builder)
    {
        $sections = [
            'options' => [
                'stacked' => TRUE,
                'tabs'    => [
                    'config'  => [
                        'title'  => 'Configuration',
                        'fields' => [
                            'featured',
                            'fall_back',
                            'icon',
                            'theme',
                            'background_image'
                        ],
                    ],
                    'content' => [
                        'title'  => 'Content',
                        'fields' => [
                            'title',
                            'price',
                            'features',
                        ],
                    ],
                    'link'    => [
                        'title'  => 'Link Options',
                        'fields' => [
                            'button_text',
                            'target'
                        ]
                    ]
                ]
            ]
        ];
    }

The last thing you need to do is prefix the above sections array with the the builders prefix so that the sections will be used.

$sections = $builder->prefixSectionFields($builder->getOption('prefix'), $sections);

$builder->setSections($sections);

In the end your sections class should look like this.

<?php namespace Emange\PricingCardsBlockExtension\Card\Support\RepeaterFieldType;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

/**
 * Class RepeaterFormSections
 *
 */
class RepeaterFormSections
{
    /**
     * Handle the sections.
     *
     * @param RepeaterFormBuilder $builder
     * @param Request $request
     */
    public function handle(RepeaterFormBuilder $builder)
    {
        $sections = [
            'options' => [
                'stacked' => TRUE,
                'tabs'    => [
                    'config'  => [
                        'title'  => 'Configuration',
                        'fields' => [
                            'featured',
                            'fall_back',
                            'icon',
                            'theme',
                            'background_image'
                        ],
                    ],
                    'content' => [
                        'title'  => 'Content',
                        'fields' => [
                            'title',
                            'price',
                            'features',
                        ],
                    ],
                    'link'    => [
                        'title'  => 'Link Options',
                        'fields' => [
                            'button_text',
                            'target'
                        ]
                    ]
                ]
            ]
        ];

        $sections = $builder->prefixSectionFields($builder->getOption('prefix'), $sections);

        $builder->setSections($sections);

    }
}