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

Filament Async Column Laravel Package

giacomomasseron/filament-async-column

Filament Async Column loads table column values asynchronously, so slow or expensive data (API calls, heavy queries, computed stats) no longer blocks your Filament tables from rendering. Cells show a placeholder and fill in when ready, keeping admin lists fast and responsive.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What it is, in TPM terms. giacomomasseron/filament-async-column is a Filament v5 table column that lets a cell paint before its value resolves. You swap Column::make() for AsyncColumn::make(), supply a per-record callback via resolveUsing(), and the cell renders a placeholder until the callback returns. It is a presentation-layer extension of Filament's column lifecycle — not a queue, not a cache, not a batching layer. Everything a TPM plans around should assume it changes perceived performance and loading-state ownership, not call volume.

Architecture fit. Narrow but genuine. The failure mode it addresses — a paginated admin table where each row triggers a remote or expensive lookup (carrier ETAs, enrichment scores, third-party pricing), so the whole table blocks on the slowest row — is recurring in the panels we build. This localizes the degradation to the affected cells and unblocks roadmap items that were previously gated on a caching/batching initiative. The v1.1.2 release is purely additive: four CSS loader presets (skeleton default, spinner, dots, bar) plus loaderColor() resolving through Filament's palette including FilamentColor::register() entries and dark mode. No change to the resolution contract.

Integration feasibility. High, per column. One Composer dependency, one class swap on targeted fields, three chained methods. Release notes state explicit backward compatibility — loadingState() retains precedence, and columns using neither new method render the same skeleton as v1.1.1 — so the version bump is a schedulable no-op independent of feature adoption. That decoupling is the single most useful property for planning: the dependency can ride a routine maintenance window while loader adoption becomes its own scoped decision.

Technical risk.

  • The load problem is hidden, not solved. A per-row closure across a 25-row page against a rate-limited API is still 25 calls. Loaders buy perceived speed; they do not buy headroom.
  • Re-render amplification is unquantified and is the top unknown. Whether resolveUsing() fires once per page load or on every sort/filter/search/pagination/Livewire poll determines the real call multiplier. Nothing in the provided materials documents this.
  • Single maintainer, 10 stars, 0 dependents. Small MIT surface bounds the worst case, and v1.1.1 shows real hygiene (SECURITY.md, Dependabot, .gitattributes-trimmed dist), but bus factor is the long-term exposure, not code quality.
  • Silent non-application. Existing loadingState() markup wins over loader(). This prevents regressions but means a design spec calling for spinners will silently not render on any table already using custom loading markup.
  • Error and timeout behavior is undocumented. The materials describe only the happy path; an indeterminate skeleton on a failed call is worse than no async at all, from a support-ticket standpoint.
  • Accessibility is a net positive and a scope reduction. All four presets halt under prefers-reduced-motion, and color resolution follows dark mode. That closes a recurring audit finding we would otherwise ticket.

Key questions.

  1. Which Filament majors are supported, and what is the support window? An unsupported major is a blocker, not a managed risk.
  2. Does resolveUsing() fire once per page load, or per re-render (sort, filter, search, paginate, poll)? What is the measured call multiplier on a realistic table?
  3. What renders on callback exception or timeout — bounded error state, or indefinite skeleton?
  4. Is there any built-in caching, deduplication, or concurrency limiting, or is that entirely ours?
  5. Does loaderColor() fail loudly or fall back silently on an unregistered color?
  6. Which of our tables already use custom loadingState() markup, and who owns updating those?
  7. What is test coverage and CI posture, given this sits in client-facing admin panels?

Integration Approach

Stack fit. Laravel + Filament v5 + Livewire tables. No new runtime, queue, or service boundary — the package lives entirely inside the existing column API, so no new mental model for engineers already fluent in Filament columns. The v1.1.2 surface is loader(), loaderColor(), and the pre-existing loadingState() escape hatch. All three accept closures evaluated per row, which is what lets design express conventions ("spinner in primary for externally-fetched values") as a documented rule rather than per-table code.

Migration path. Near-zero friction. v1.1.1 → v1.1.2 renames nothing, changes no defaults, and preserves the default skeleton for untouched columns. Plan it as two separate line items: the dependency bump (no-op diff, routine window) and loader adoption (opt-in UX decision, can trail by a sprint). Conflating them turns a five-minute bump into a design review.

Compatibility.

  • Confirm the pinned Filament major is in the supported range before anything else. This is the gate.
  • Inventory loadingState() usage. Custom markup continues to win over loader() — protects us from regressions, but sets an expectation gap with design.
  • Validate loaderColor() against our palette in light and dark, especially custom FilamentColor::register() entries. Panel color registration must occur before table render, and low-contrast tints are the likely cosmetic defect.
  • Establish a review convention that loader()/loaderColor() closures stay side-effect free. They are styling decisions, not a second place to perform I/O — this is the easiest way to accidentally double per-row calls.

Sequencing.

  1. Verify. Confirm Filament major support, license, test coverage; run our suite against the bump in a branch. Expected outcome: no-op diff, mergeable independently.
  2. Measure. Spike one internal table with a genuinely slow column, instrumenting per-render call counts. This answers the amplification question empirically and tells us whether caching/throttling is a prerequisite or a follow-up. Do not skip this step — it determines whether the rollout plan is "adopt broadly" or "adopt behind caching."
  3. Pilot. Apply loader presets on that one table. Pair with caching and throttling in application code. Agree the convention with design: skeleton as default, spinner for waits past a threshold, color by semantic severity.
  4. Roll out. Extend to further slow-data tables; migrate any loadingState() holdouts explicitly rather than assuming presets apply.
  5. Standardize. Document the convention in the panel style guide so it becomes a rule, not a per-ticket decision.

Operational Impact

Maintenance. Low code surface, MIT, additive-only recent releases. The real maintenance cost is not upgrading the package — it is the surrounding work the package does not do: caching, throttling, and retry policy for the underlying calls. Budget for that in the same initiative, or the perceived-performance win gets spent immediately on real load.

Support. Support load concentrates in two places: ambiguous skeletons (a cell that never resolves reads as a broken table, and generates tickets indistinguishable from a genuine outage) and missing spinners on tables where loadingState() silently wins. Both are eliminated by documentation and a clear convention, not by code. Also note the dependency is single-maintainer: we should pin to a tested minor, track upstream activity, and keep a documented one-afternoon fallback (revert to a standard column with a synchronous or preloaded value).

Scaling. The package scales with the number of columns, not with data volume — and that is the wrong axis to optimize for free. Every additional AsyncColumn multiplies per-row remote calls by re-render count. Scaling guidance is therefore: adopt on a small number of genuinely slow columns, never as a default column type, and treat any expansion as requiring a caching story first. Also: does not batch, queue, or limit concurrency. Table-level or bulk async enrichment is a different architectural problem and should be scoped separately.

Failure modes.

  • Indeterminate skeleton on callback exception or timeout — the highest-severity UX failure, since it is indistinguishable from slowness. Verify and, if unbounded, wrap callbacks with our own timeout-and-fallback.
  • Re-render storm — sorts/filters/polls re-triggering per-row calls, producing a load spike under exactly the interactive use a fast table encourages. Mitigated by caching, but only if step 2 measures it.
  • Silent non-application — presets ignored where loadingState() exists.
  • Cosmetic — unregistered or low-contrast loaderColor() in one of the two themes.
  • Abandonment — upstream goes stale; bounded by small surface and the fallback plan.

Ramp-up. Effectively zero for anyone who has written a Filament column: one method chain, no new concepts, no frontend build step (pure CSS, no JS bundle). The learning is not technical, it is convention — designers and engineers agreeing which loader means what, and reviewers knowing that closure bodies stay side-effect free. Plan a short written convention alongside the pilot rather than training. Stakeholder framing should stay narrow and honest: this is a small additive release that keeps data-heavy admin tables responsive when individual values come from outside services, it gives us accessible, theme-aware loading states we would otherwise build and own, it is backward compatible with no migration and no downtime — and the caveat is dependency risk, not technical risk.

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.
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox