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 Spreadsheet Grid Laravel Package

asignua/filament-spreadsheet-grid

Add spreadsheet-style editing to Filament with an interactive grid component. Edit cells and rows inline, navigate with the keyboard, and manage tabular data fast—ideal for bulk data entry and quick admin panel workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

This is an inline-editable data grid for Livewire: cells are edited in place, validated on the client, saved to Eloquent, and read back through the table's query. v1.0.1 is a behavioral-hardening release rather than a feature drop — the compiled CSS and JS are unchanged (only jsdom/esbuild dev dependencies moved), so upgrading is a composer update with no asset republish or rebuild.

First steps:

  1. Upgrade and run your existing grid test suite before touching code. The risky changes are all in parsing/validation, not in markup, so a green suite means you can adopt the fixes incrementally.
  2. Look first at your column type definitions — number(), boolean columns, select(), date() — and the rules attached to each. That is where every change in this release lands.
  3. Start with one grid that has a number() column fed by user paste. Confirm 1.250 now stays dirty with an error instead of silently becoming 1.25, and that a second paste of the same text no longer turns into a valid 1.25 (the x1000 corruption class of bug).

The first real use case: a back-office table where operators paste columns out of a spreadsheet. That workflow exercises fill down/right, copy/paste, per-cell error tracking, and read-back after save — i.e. all of v1.0.1.

Implementation Patterns

Type columns by intent, not by storage. Use number()/boolean columns only where the machine form is unambiguous. Anything where 1.250 has business meaning (currency with three decimals, version strings, SKUs that look numeric) should be a text column with an explicit parser, because the server still cannot tell a user-typed 1.250 from the grid's own held 1.250 and will accept it for number() columns — the release notes flag this as an open owner decision, so don't build on it.

Rely on per-cell dirty state as your error channel. A cell the client cannot read stays dirty with its error and is never sent. That means you can trust "no request" as "no bad write" and don't need a server-side pre-parse pass for client-entered values. Surface the dirty count in the UI; it's a cheap proxy for "operator has unresolved cells".

Validate under the column's own name. As of v1.0.1, user rules resolve under the column name, so unique:products and exists:skus string rules work directly instead of needing a wrapper or a Rule::unique reconstruction. Prefer string rules where they're legible; fall back to rule objects only where you need where() clauses.

Let fill and paste be the bulk-edit path. Fill down/right and copy/paste are tracked per source cell, so a valid 1.234 adjacent to an invalid cell holding the same text still fills as valid, and in a mixed range only the invalid cells stay invalid. Design bulk entry around this rather than adding your own mass-update endpoint — you get per-cell error attribution for free.

Treat save as a round trip, then trust the read-back. The post-save read-back now goes through the table's query, so pivot columns, joins, and query-level formatting keep their values in the grid. Pattern: write via the model, let the grid re-read, and avoid manually patching the row in JS — you'll fight the read-back.

Handle the model-event veto explicitly. A saving listener returning false is now reported as failed rather than saved. If you use that hook for approval gates or locking, wire the failure into a user-visible notice; before this release it looked like a successful save.

Use the filter's base query for soft-deleted work. Rows revealed by a filter's base query — e.g. TrashedFilter set to "With trashed" — can now be saved. This makes restore/edit flows inside the grid viable instead of read-only.

Gotchas and Tips

  • required() now rejects whitespace-only text, on both client and server. Any legacy column where " " was a meaningful placeholder will start failing validation after upgrade. Audit before shipping.
  • Pasting an invalid cell back keeps it invalid. Copying an invalid cell puts its raw text on the clipboard (a boolean maybe is no longer coerced to FALSE), so round-tripping preserves the error instead of laundering it into a value. Don't "fix" this in a clipboard handler.
  • Filling or pasting the grid's own copy over an invalid cell does resolve it when the source is valid — the machine form is read. That's the intended recovery path; document it for operators.
  • number() still accepts 1.250 server-side. Client keeps the cell dirty, but a request that arrives with that text (e.g. from an API caller or a bypassed client) will be stored. If you need strictness today, add explicit validation on the column rather than waiting for the owner decision.
  • A save response no longer wipes client errors for cells outside the request. If you previously relied on a save to reset the whole error state, you now need an explicit reset. Conversely, partial saves are safe — don't add your own error-merging shim.
  • A value missing from a select's options is now listed rather than silently cleared. Leaving an untouched select or date editor no longer drops a stored value the control can't render. This surfaces data drift that used to be invisible — good for debugging, but expect a wave of "why is this option here" questions in staging.
  • Editors survive Livewire re-renders. The open cell editor is kept out of the morph and restored if it disappears. This means you no longer need wire:ignore hacks around the grid; if you added them for this reason, remove them — they fight the built-in handling.
  • Regression-test the parser boundaries, not the UI. The upgrade is asset-identical, so the only meaningful test surface is: ambiguous numbers with trailing zeros, unknown boolean words, mixed valid/invalid ranges for fill and paste, unique/exists rules, and saving a trashed row.
  • Debugging tip: when a cell "won't save" with no server-side trace, it's almost certainly dirty — the client never sent it. Check the client-side error state before reaching for logs.
  • The stray .table utility is gone from the compiled CSS. If you were leaning on that class as an incidental side effect of the package stylesheet, define it yourself.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings