Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Table Widget Laravel Package

digital-creative/table-widget

Digital Creative's Table Widget adds configurable table widgets to Laravel admin panels, making it easy to display sortable, filterable, paginated data on dashboards. Ships with sensible defaults and flexible column configuration for quick, clean reporting views.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a small, single-purpose package: it adds a table-rendering widget to the digital-creative/nova-dashboard ecosystem. Treat the source as the documentation — there is no docs site, and the README is thin.

Install and wire-up

composer require digital-creative/table-widget
php artisan vendor:publish --tag=table-widget-assets   # if the tag exists; check the service provider

Requirements to verify before installing:

  • laravel/nova version in composer.json (^4.0 vs ^5.0 — the last release was Oct 2023, so Nova 5 support is unconfirmed)
  • digital-creative/nova-dashboard must already be installed and working; this widget is useless standalone

Where to look first

  1. src/ — find the base widget class (likely TableWidget or similar). Everything you need to know about columns, query, and rendering is there.
  2. The parent package's widget contract (nova-dashboard) — your widget ultimately has to satisfy it.
  3. resources/js/ — tells you what props the Vue component expects, which is often clearer than the PHP side.

First use case

The highest-value, lowest-risk entry point is a read-only "recent activity" table on your main dashboard — e.g. latest orders, signups, or failed jobs. It gives stakeholders an at-a-glance view without building a full Nova resource page, and it exercises the column and query API without touching auth or write paths.

// app/Nova/Dashboards/Widgets/RecentOrders.php
class RecentOrders extends TableWidget
{
    public function columns(): array
    {
        return [
            // Column API mirrors Nova fields in most Digital Creative packages —
            // confirm against src/ before relying on this.
            TextColumn::make('Reference', 'reference'),
            TextColumn::make('Customer', 'customer.name'),
            BadgeColumn::make('Status', 'status'),
            DateColumn::make('Placed', 'created_at'),
        ];
    }

    public function query(): Builder
    {
        return Order::query()->latest()->limit(10);
    }
}

Then register it in the dashboard config/class as you would any other widget.

Implementation Patterns

Resource-backed vs. query-backed tables. Two viable shapes: point the widget at an existing Nova resource (reusing indexQuery, fields, and authorization), or hand it a Builder/Eloquent query. For internal admin dashboards, resource-backed wins — you get filters, sorting, and policy enforcement for free and don't duplicate column definitions. For purpose-built summaries ("top 10 overdue invoices"), query-backed is leaner and avoids leaking a full resource surface.

One widget per question. Resist a single mega-table with tabs. Dashboards in nova-dashboard are typically composed of independent widgets; small, single-purpose tables load faster and fail in isolation. Name them by the question they answer (OpenTicketsBySeverity, not TicketsTable).

Reuse Nova field definitions. If the column API accepts Nova Field instances, define columns once on the resource and reference them, or extract a trait. This keeps the dashboard table and the resource index page visually and semantically consistent — same formatters, same badge colors.

Parameterize the query with dashboard context. If the parent package passes dashboard/user context into widgets, resolve the query against request()->user() and any active team/tenant scope. Hardcoded auth()->user() inside query() breaks queue rendering and any future impersonation features.

Compose with existing Nova concepts where possible. Lenses and filters are a proven way to express "which rows." If the widget accepts a lens or a filter set, prefer that over reimplementing filter logic in a closure.

Eager-load aggressively. Widgets render on the dashboard landing page for every admin — this is the most-hit page in the app. ->with(['customer', 'assignee']) in query() is not optional; an N+1 here scales with every dashboard load.

Cache the result, not the widget. Wrap expensive aggregate queries in Cache::remember() keyed on the query parameters plus a short TTL (60–300s). Nova widgets are stateless enough that a per-request cache is wasted effort; a per-minute cache transforms a slow dashboard into a fast one.

Gotchas and Tips

Version drift is the real risk. Last release Oct 2023, 7 stars, zero dependents. Before committing, install it in a throwaway Nova 5 project and confirm the ServiceProvider bootstraps, assets compile, and the Vue component mounts. If it targets Nova 4 only, pin Nova accordingly or fork and patch.

The README is not the API. For any method not demonstrated in the README, read src/. Assumptions about column classes, sorting callbacks, or pagination will silently produce an empty or mis-rendered table rather than an exception — the failure mode is visual, not loud.

Silent empty tables. If the widget renders but shows no rows, check in this order: (1) query() returning rows in tinker, (2) the dashboard widget is registered with the correct class and is authorized for the current user, (3) the JS assets are actually published and loaded (npm run build in the parent app if assets are Vite-compiled). A missing asset bundle often yields a blank widget with no console error.

Authorization is probably not automatic. Unlike Nova resources, a widget is a UI block — it may not consult policies when rendering rows. If the table exposes sensitive data (revenue, PII), gate the widget itself via canSee()/authorize() on the dashboard or the widget, and scope the query by user.

Computed/derived columns break sorting and pagination. If you add a column backed by an accessor or selectRaw, sorting and any server-side pagination that the widget applies will likely fail or reorder incorrectly. Prefer raw columns; if you must compute, do it with a subquery alias so the database can sort it.

Dark mode and Tailwind. Nova 4/5 ship Tailwind with dark mode. Custom column renderers or raw HTML will look wrong in dark mode. Use Nova's built-in components/classes rather than inline styles, and eyeball the widget in both themes before shipping.

Testing. You can unit-test query() and columns() without mounting the Vue component — assert the builder emits expected SQL and the column array has the right keys. Skip end-to-end widget rendering tests; the cost/benefit isn't there for a 7-star dependency.

Extension point of last resort. With zero dependents and low activity, expect to vendor the package (composer require → copy to packages/ with a path repository) if you need a fix. Budget a day for that, and keep the fork under your namespace so a future Nova upgrade doesn't strand you.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource