#[Ghost] attribute
Apply to a component class — no view changes required:
use Ghostwire\Attributes\Ghost;
#[Ghost(mode: 'synthesize', delay: 200, hold: 400)]class ProductTable extends Component{ // ...}Parameters
Section titled “Parameters”| Parameter | Type | Default | Meaning |
|---|---|---|---|
mode | 'synthesize'|'freeze'|'off' | 'synthesize' | Loading strategy for this component |
only | array<string>|null | null | Actions that activate the ghost |
except | array<string>|null | null | Actions that never activate it |
delay | int|null | null (package default: 120ms) | Delay before the ghost appears |
hold | int|null | null (package default: 300ms) | Minimum visible duration |
rows | int|null | null | Repeat-row hint for an empty host |
poll | bool | false | Allow polled messages to activate the ghost |
sync | bool | false | Allow property-only (sync) messages to activate it |
lazy | bool | false | Reuse the learned tree as the lazy placeholder |
panels | bool | false | Promote visually distinct containers to their own panel bone |
More examples
Section titled “More examples”Action filtering — restrict or exclude specific actions from the class-level config:
#[Ghost(only: ['loadMore', 'applyFilters'])]class ProductList extends Component{ // ...}Only loadMore and applyFilters activate the ghost; every other action leaves it alone.
#[Ghost(except: ['toggleFavorite'])]class ProductList extends Component{ // ...}Every action activates the ghost except toggleFavorite.
#[Ghost(rows: 5)]class OrderTable extends Component{ // ...}Renders 5 skeleton rows when the table has no data yet — the attribute equivalent of wire:ghost.rows.5.
#[Ghost(poll: true)]class LiveTicker extends Component{ // ...}Lets a wire:poll-driven refresh activate the ghost too; polled messages are silent by default.
#[Ghost(sync: true)]class SearchResults extends Component{ // ...}Lets a property-only update (e.g. wire:model.live) activate the ghost too; sync messages are silent by default.
#[Ghost(lazy: true)]class Dashboard extends Component{ // ...}Reuses a previously learned Bone Tree as the lazy-loading placeholder — see Learning for the full setup.
#[Ghost(panels: true)]class ProductGrid extends Component{ // ...}Cards with a visible background, border, or shadow each get their own filled panel bone — see How it works.
Precedence cascade
Section titled “Precedence cascade”Seven levels, most to least specific:
- Directive modifier on the element — e.g.
wire:ghost.freeze - Directive expression / action targeting — e.g.
wire:ghost="applyFilters" #[Ghost]on the executing action’s method#[Ghost]on the component class#[Ghost]inherited from a base class or traitconfig/ghostwire.php- Package defaults
The wire:ghost directive on the element outranks the #[Ghost] attribute: a directive-level setting overrides whatever the attribute levels declare, field by field. Any field a given level doesn’t declare falls through to the next. Inspect exactly which level decided a component’s live configuration with:
php artisan ghost:inspectMethod-level targeting
Section titled “Method-level targeting”#[Ghost(mode: 'freeze')]class ReportTable extends Component{ #[Ghost(mode: 'synthesize', delay: 50)] public function refresh() { /* ... */ }}refresh()’s own attribute overrides the class-level default for that action only.