You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Nova:实现行点击弹出详情及再次点击折叠功能求助

Implementing Click-to-Expand/Collapse Row Details in Laravel Nova

Hey there! I’ve built this exact feature for a few Nova projects, so let’s walk through a straightforward, maintainable approach using tools Nova already includes (Alpine.js and Blade):

Step 1: Add Toggle Logic to Your Resource

First, we’ll inject Alpine.js state management into your Nova resource’s index page. Open your resource file (e.g., app/Nova/Order.php) and add these methods:

// Handle the expand/collapse state with Alpine
public static function script()
{
    return <<<'JS'
        document.addEventListener('alpine:init', () => {
            Alpine.data('rowExpander', () => ({
                expandedId: null,

                toggle(rowId) {
                    this.expandedId = this.expandedId === rowId ? null : rowId;
                }
            }));
        });
    JS;
}

// Override how Nova renders table rows to include our expandable section
public function tableRow($resource)
{
    return view('nova.partials.expandable-row', [
        'resource' => $resource,
        'detailsHtml' => $this->getRowDetails($resource),
        'columnCount' => count($this->indexFields()),
    ]);
}

// Prepare the details content for each row
protected function getRowDetails($resource)
{
    // Customize this to return whatever details you need
    return view('nova.partials.row-details', ['resource' => $resource])->render();
}

Step 2: Create the Blade Views

Next, make two Blade partials to handle the row structure and details content.

resources/views/nova/partials/expandable-row.blade.php

This wraps the main clickable row and the expandable details section:

<div x-data="rowExpander">
    <!-- Main clickable row -->
    <tr @click="toggle({{ $resource->id }})" class="cursor-pointer hover:bg-gray-50 transition-colors">
        @foreach($this->indexFields() as $field)
            <td>{!! $field->resolveForDisplay($resource) !!}</td>
        @endforeach
    </tr>
    <!-- Expandable details row -->
    <tr x-show="expandedId === {{ $resource->id }}" class="bg-gray-50">
        <td colspan="{{ $columnCount }}" class="p-4">
            {!! $detailsHtml !!}
        </td>
    </tr>
</div>

resources/views/nova/partials/row-details.blade.php

Customize this to show your resource’s specific details:

<div class="grid grid-cols-2 gap-4">
    <div class="space-y-1">
        <p class="text-sm font-semibold text-gray-700">Created At</p>
        <p class="text-sm text-gray-600">{{ $resource->created_at->format('F j, Y g:i A') }}</p>
    </div>
    <div class="space-y-1">
        <p class="text-sm font-semibold text-gray-700">Updated At</p>
        <p class="text-sm text-gray-600">{{ $resource->updated_at->format('F j, Y g:i A') }}</p>
    </div>
    <!-- Add more fields as needed -->
    @if($resource->notes)
        <div class="col-span-2 space-y-1">
            <p class="text-sm font-semibold text-gray-700">Notes</p>
            <p class="text-sm text-gray-600">{{ $resource->notes }}</p>
        </div>
    @endif
</div>

Step 3: Optional Styling Tweaks

Add a bit of CSS to make the interaction feel smoother. Inject it via your resource’s style method:

public static function style()
{
    return <<<'CSS'
        .cursor-pointer {
            user-select: none;
        }
        .bg-gray-50 td {
            border-top: 1px solid #e5e7eb;
        }
    CSS;
}

Bonus Enhancements

  • Multiple Expanded Rows: If you want to let users expand multiple rows at once, change expandedId to an array and adjust the toggle logic:
    expandedIds: [],
    toggle(rowId) {
        const index = this.expandedIds.indexOf(rowId);
        if (index === -1) {
            this.expandedIds.push(rowId);
        } else {
            this.expandedIds.splice(index, 1);
        }
    }
    
    Then update the x-show to expandedIds.includes({{ $resource->id }}).
  • Lazy Loading: For heavy details, replace the static getRowDetails with an AJAX call in the toggle function to fetch data on demand.
  • Keyboard Support: Add tabindex="0" to the <tr> and a @keyup.enter="toggle({{ $resource->id }})" directive for accessibility.

This setup works seamlessly with Nova’s existing table system, keeps users on the index page, and gives them quick access to detailed info without navigating away.

内容的提问来源于stack exchange,提问作者Oleksandr Roskovynskyi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 10:42:46