Unpacking Flexible Content Fields

It is easy to output flexible content data using the @flexibleField directive but sometimes you will need something that is too specific for a layout override or too complicated to pull directly from the row inside a template. For these cases, a better approach is to set up a function that can manually unpack the data and return it to the template in a useful format.

To keep the code separate you should start by setting up a RowSpec as a class (see row-specs)

In this class, add a public unpack method that iterates over the expected data and returns it in a new format that is more useful for your template. An simple example of a row-spec with a text label and a select fields might look like this:

<?php

namespace App\Crud\RowSpecs;

use Yadda\Enso\Crud\Forms\FlexibleContentSection;

class MyRowSpec extends FlexibleContentSection
{
    /**
     * Return just the data from the flexible content section in a more useable format
     *
     * @param FlexibleRow $flexible_row_data
     * @return array
     */
    public function unpack($flexible_row)
    {
        $blocks = $flexible_row->getBlocks();

        $data = (object) [
            'label' => self::getLabelContent($blocks),
            'alignment' => self::getAlignmentContent($blocks),
        ];

        return $data;
    }

    /**
     * Get the label from the given collection of blocks.
     *
     * @param Collection $blocks
     * @return string|null
     */
    protected static function getLabelContent($blocks)
    {
        return $blocks->has('label') ? $blocks->get('label')->getContent() : '';
    }

    /**
     * Get the actual value of the chosen alignment option from the
     * given collection of blocks, or a default if not selected.
     *
     * @param Collection $blocks
     * @return string|null
     */
    protected static function getAlignmentContent($blocks)
    {
        if (
            !$blocks->has('alignment')
            || is_null($blocks->get('alignment')->getContent())
            || !isset($blocks->get('alignment')->getContent()['id'])
        ) {
            return self::$default_alignment;
        }

        return $blocks->get('alignment')->getContent()['id'];
    }
}

This simply checks the row for data, fills in with defaults, and returns it as an object.

In the template that you create to render this row_spec, you can then make a call to this unpack function at the top of your template, passing in the row.

@php
  $data = \App\Crud\RowSpecs\ExampleRowSpec::unpack($row);
@endphp

You then have the data available to use in a format that you have control over, stored in the $data variable.

@if($data->label && $data->alignment)
    ...
@endif