Skip to content

Create a Detail View

Detail pages display and edit individual records with forms.

Noerd Example App

File Locations

YAML Configuration:

app-configs/{app}/details/{name}-detail.yml

Livewire Component:

app-modules/{module}/resources/views/components/⚡{name}-detail.blade.php

YAML Configuration

Example: app-configs/accounting/details/customer-detail.yml

yaml
title: Customer Details
description: ''
tabs:
  - number: 1
    label: Master Data
  - label: Invoices
    component: invoices-list
    arguments:
      customerId: $customerId
    requiresId: true
fields:
  - name: detailData.name
    label: Name
    type: text
    required: true
  - name: detailData.company_name
    label: Company Name
    type: text
  - name: detailData.email
    label: Email
    type: text
  - name: detailData.phone
    label: Phone
    type: text
  - name: detailData.address
    label: Address
    type: text
  - name: detailData.zipcode
    label: Zip Code
    type: text
  - name: detailData.city
    label: City
    type: text

Detail Properties

PropertyDescription
titlePage title (translation key)
descriptionOptional description text
tabsArray of tab definitions
fieldsArray of form field definitions

Tab Properties

PropertyDescription
numberTab index (1-based)
labelTab label (translation key)
componentEmbedded Livewire component
argumentsArguments passed to embedded component
requiresIdOnly show tab when editing existing record

Field Properties

PropertyDescription
nameProperty path (e.g., detailData.name)
labelField label (translation key)
typeField type (text, textarea, checkbox, relation, etc.)
requiredMark field as required
colspanGrid column span (1-12)
tabTab number (defaults to 1)

Livewire Component

Example: customer-detail.blade.php

php
<?php

use Livewire\Component;
use Noerd\Traits\NoerdDetail;
use Nywerk\Customer\Models\Customer;

new class extends Component {
    use NoerdDetail;

    public const DETAIL_CLASS = Customer::class;

    public function store(): void
    {
        $this->validateFromLayout();

        $this->detailData['tenant_id'] = auth()->user()->selected_tenant_id;
        $customer = Customer::updateOrCreate(['id' => $this->modelId], $this->detailData);

        $this->showSuccessIndicator = true;

        if ($customer->wasRecentlyCreated) {
            $this->modelId = $customer->id;
        }
    }

    public function delete(): void
    {
        $customer = Customer::find($this->modelId);
        $customer->delete();
        $this->closeModalProcess($this->getListComponent());
    }
}; ?>

<x-noerd::page :disableModal="$disableModal">
    <x-slot:header>
        <x-noerd::modal-title>Kunde</x-noerd::modal-title>
    </x-slot:header>

    <x-slot:footer>
        <x-noerd::delete-save-bar :showDelete="isset($modelId)"/>
    </x-slot:footer>
</x-noerd::page>

Key Concepts

  • Trait: NoerdDetail provides $detailData, $modelId, $pageLayout, and helper methods
  • Constant: Only DETAIL_CLASS = Model::class is required
  • Properties: $detailData (array) for form binding, $modelId (from trait) for the record ID
  • mount(): Handled by the trait automatically - no need to define it
  • validateFromLayout(): Validates against YAML-defined rules
  • $this->getListComponent(): Automatically determines the associated list component
  • The Eloquent model is never stored as a component property

Naming Conventions

  • Lists: {plural}-list.blade.php (e.g., customers-list.blade.php)
  • Details: {singular}-detail.blade.php (e.g., customer-detail.blade.php)
  • Components must be placed directly in the components/ folder, not in subfolders

Next Steps