View on GitLab

Composite

x-larastrap::composite is a tool to create complex Custom Elements and aggregate multiple Inputs in a single, reusable component.

It is a subclass of Enclose but also somehow behaves like a Typography component, with a few specific behaviors.

node

Like for Typography components, you can define the wrapping HTML node to be used while rendering the Composite.

$slot

In Composite, it is possible to use the string $slot within the prependNodes / appendNodes parameters, to be able to place the internal contents of the component (which is still a Container) in any place of the hierarchy.

This is a card
Contents of the card
[
    'customs' => [
        'card' => [
            'extends' => 'composite',
            'params' => [
                'node' => 'div',
                'classes' => ['card'],
                'prependNodes' => [
                    [
                        'extends' => 't',
                        'params' => [
                            'node' => 'div',
                            'classes' => ['card-header'],
                            'contentfrom' => 'header'
                        ]
                    ],
                    [
                        'extends' => 't',
                        'params' => [
                            'node' => 'div',
                            'classes' => ['card-body'],
                            'innerAppendNodes' => [
                                '$slot'
                            ]
                        ]
                    ]
                ]
            ]
        ]
    ]
]
<x-larastrap::card header="This is a card">
    Contents of the card
</x-larastrap::card>
<div id="composite-b3adc526" class="card" header="This is a card">
  <div id="basenode-83133f56" class="card-header" header="This is a card">
    This is a card
  </div>
  <div id="basenode-d908208e" class="card-body" header="This is a card">
    Contents of the card
  </div>
</div>

name

As Composite is mainly intended to create widgets to be used within Forms, and to collect multiple inputs for a given entity related to the main Model assigned to the Form itself, when the name parameter is specified it retrieves the named relation from the parent obj and use it as local obj .

Plus, the value assigned to the "name" attribute of each child HTML inputs is serialized to be accessed with dot notation when submitted to the Laravel Controller.

[
    'customs' => [
        'user-edit' => [
            'extends' => 'composite',
            'params' => [
                'node' => 'div',
                'classes' => ['card', 'mb-1'],
                'appendNodes' => [
                    [
                        'extends' => 't',
                        'params' => [
                            'node' => 'div',
                            'classes' => ['card-body'],
                            'innerAppendNodes' => [
                                [
                                    'extends' => 'text',
                                    'params' => [
                                        'label' => 'Name',
                                        'name' => 'name'
                                    ]
                                ],
                                [
                                    'extends' => 'email',
                                    'params' => [
                                        'label' => 'E-Mail',
                                        'name' => 'email'
                                    ]
                                ],
                            ]
                        ]
                    ]
                ]
            ]
        ]
    ]
]
@php
$obj = App\Models\User::has('boss')->inRandomOrder()->first();
@endphp

<x-larastrap::form :obj="$obj">
    <x-larastrap::field label="The Main User">
        <x-larastrap::user-edit />
    </x-larastrap::field>
    <x-larastrap::field label="The Boss">
        <x-larastrap::user-edit name="boss" />
    </x-larastrap::field>
</x-larastrap::form>
<form id="form-b4cf537f" class="" method="post" name="form-b4cf537f">
  <input type="hidden" name="_token" value="sLlI7eBKX7nyLbm8q6aiD5BA9JhIfzV1auq4mNIE" autocomplete="off">
  <div class="row mb-2">
    <label for="field-4899b886" class="col-4 col-form-label">The Main User</label>
    <div class="col-8">
      <div id="composite-d1c92267" class="card mb-1">
        <div id="basenode-f8dca14c" class="card-body">
          <div class="row mb-2">
            <label for="input-1afe04cd" class="col-4 col-form-label">Name</label>
            <div class="col-8">
              <input id="input-1afe04cd" type="text" class="form-control" name="name" value="Jules Wunsch">
            </div>
          </div>
          <div class="row mb-2">
            <label for="input-e467f03f" class="col-4 col-form-label">E-Mail</label>
            <div class="col-8">
              <input id="input-e467f03f" type="email" class="form-control" name="email" value="daniel.arlie@example.net">
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="row mb-2">
    <label for="field-69e4678b" class="col-4 col-form-label">The Boss</label>
    <div class="col-8">
      <div id="composite-23df7e31" class="card mb-1">
        <div id="basenode-5d9bae3d" class="card-body">
          <div class="row mb-2">
            <label for="input-d0667286" class="col-4 col-form-label">Name</label>
            <div class="col-8">
              <input id="input-d0667286" type="text" class="form-control" name="boss[name]" value="Prof. Elmo Rosenbaum">
            </div>
          </div>
          <div class="row mb-2">
            <label for="input-63920e11" class="col-4 col-form-label">E-Mail</label>
            <div class="col-8">
              <input id="input-63920e11" type="email" class="form-control" name="boss[email]" value="zemlak.noel@example.com">
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="col-12 text-end">
    <button id="button-faf552ff" class="btn btn-primary" type="submit">Save</button>
  </div>
</form>