PHP code example of unnathianalytics / laragrid

1. Go to this page and download the library: Download unnathianalytics/laragrid library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

unnathianalytics / laragrid example snippets


use App\Models\Resort;
use LaraGrid\Actions\Action;
use LaraGrid\Aggregate;
use LaraGrid\Columns\{SerialColumn, TextColumn, IntegerColumn, DateColumn, ComputedColumn};
use LaraGrid\Filters\SelectFilter;
use LaraGrid\Grid;
use LaraGrid\Livewire\WithLaraGrid;
use LaraGrid\Support\CellHtml;
use Livewire\Component;

class ResortsIndex extends Component
{
    use WithLaraGrid;   // ← see note below
            ->filters([
                SelectFilter::make('type')->label('Type')
                    ->options(fn () => Resort::distinct()->orderBy('type')->pluck('type', 'type')),
                SelectFilter::make('visibility')->label('Visibility')
                    ->options(['show' => 'Show', 'hide' => 'Hide']),
            ])
            ->columns([
                SerialColumn::make(),
                TextColumn::make('name')->label('Resort')->sortable()->searchable()->grow(),
                TextColumn::make('type')->sortable()->width(120),
                IntegerColumn::make('hits')->sortable()->width(90),
                ComputedColumn::make('status')->html()->width(90)
                    ->state(fn (array $row) => $row['visibility'] === 'show'
                        ? CellHtml::badge('green', 'Show')
                        : CellHtml::badge('zinc', 'Hide')),
                DateColumn::make('created_at')->label('Added')->sortable()->width(110),
            ])
            ->footer([Aggregate::sum('hits')->format('number')])
            ->exportable(['csv', 'xlsx', 'pdf'])     // toolbar Export control — see Exports
            ->actions([
                Action::make('edit')->icon('✎')->url(fn ($row) => route('resorts.edit', $row['id'])),
                Action::make('delete')->icon('✕')->confirm('Delete this resort?')
                    ->call(fn (array $row) => Resort::whereKey($row['id'])->delete()),
            ])
            ->stickyHeader()->striped()->maxHeight('70vh')];
    }

    public function render()
    {
        return view('livewire.resorts-index');
    }
}

use LaraGrid\Columns\{SerialColumn, SearchSelectColumn, IntegerColumn, DecimalColumn, FormulaColumn, TextColumn};
use LaraGrid\Editing\RowContext;

class BookingEntry extends Component
{
    use WithLaraGrid;

    /** @var list<array<string, mixed>> */
    public array $lines = [];

    public function mount(): void
    {
        $this->lines = $this->gridMountRows('lines');   // seeds defaultRows via the factory
    }

    protected function grids(): array
    {
        return ['lines' => Grid::make('lines')
            ->editable()
            ->rowsFrom('lines')                         // binds public array $lines
            ->authorize(fn () => $this->authorize('booking.create'))
            ->defaultRows(3)
            ->newRowUsing(fn () => ['nights' => 1])     // template for seeded AND inserted rows
            ->minRows(1)
            ->autoAppend()                              // Enter past the last cell grows the grid
            ->persistDraft('local', 'booking:new')      // opt-in IndexedDB crash/reload recovery
            ->focusOnMount()
            ->focusOutTo('[data-save]')                 // Tab past the last cell lands on Save
            ->columns([
                SerialColumn::make(),
                SearchSelectColumn::make('resort_id')->label('Resort')
                    ->optionsUsing(fn (string $term) => Resort::query()
                        ->when($term !== '', fn ($q) => $q->where('name', 'like', "%{$term}%"))
                        ->limit(50)->get(['id', 'name'])
                        ->map(fn ($r) => ['value' => (string) $r->id, 'label' => $r->name])
                        ->all())
                    ->onSelect(function (RowContext $row, mixed $value): void {
                        // Enrichment: the pick pre-fills the rate; write-backs reconcile
                        // into the client row automatically.
                        $row->set('rate', Resort::whereKey($value)->value('comparison_tariff'));
                    })
                    ->

SearchSelectColumn::make('item_id')
    ->endOfListOption()                                  // default label: <-- End of List -->
    // ->endOfListOption('— Done adding lines —')        // custom label
    // ->endOfListOption(allowOnEmpty: true)             // offer it even on an empty grid

Grid::make('lines')
    ->editable()->rowsFrom('lines')->autoAppend()
    ->focusOutTo('[data-save]')        // operator tabs off the end → Save
    ->onCompleteFocus('[data-save]')   // operator picks "End of List" → lgrid:complete + Save

    ->focusOutTo('#remarks')
    ->onCompleteFocus('[data-save]')

// 1. Per-pick enrichment (SearchSelectColumn): the pick pre-fills dependent cells.
SearchSelectColumn::make('item_id')
    ->onSelect(function (RowContext $row, mixed $value): void {
        $item = Item::find($value);
        $row->set('rate', $item?->rate);
        $row->set('uom', $item?->uom);
    })

// 2. Grid-wide row consistency: runs after EVERY applied cell change (typing, paste,
//    fill-down). Example — derive nights from a date range:
->afterCellChange(function (RowContext $row, string $column): void {
    if (! in_array($column, ['fromDate', 'toDate'], true)) {
        return;
    }
    if ($row->get('fromDate') && $row->get('toDate')) {
        $nights = Carbon::parse($row->get('fromDate'))
            ->diffInDays(Carbon::parse($row->get('toDate')), false);
        $row->set('nights', $nights >= 1 ? (int) $nights : null);
    }
})

// 3. After a row removal — recompute host-side chrome (an "Allocated" total, a balance badge):
->afterRowRemove(fn () => $this->recomputeTotals())

TextColumn::make('type')->hiddenByDefault()

use LaraGrid\Columns\FocusMode;

// Variable (Default): Always receives sequential keyboard focus
TextColumn::make('party_name')
    ->focusMode(FocusMode::Always);

// Semi-Variable: Skipped on keyboard navigation (Tab/Enter), focusable and editable on mouse click
DecimalColumn::make('qty')
    ->focusMode(FocusMode::Manual, default: 1);

// Fixed: Skipped on keyboard navigation, read-only / non-editable, dynamic Closure default
DateColumn::make('vch_date')
    ->focusMode(FocusMode::Never, default: fn () => now()->format('Y-m-d'));

->actions([          // per-row buttons in a trailing column
    Action::make('edit')->icon('✎')->url(fn ($row) => route('items.edit', $row['id'])),
    Action::make('archive')->confirm('Archive?')->visible(fn ($row) => ! $row['archived'])
        ->call(fn (array $row) => Item::whereKey($row['id'])->archive()),
])
->bulkActions([      // run over checked rows; a selector gutter + toolbar bulk bar appear
    Action::make('delete')->confirm('Delete selected?')
        ->call(fn (array $keys) => Item::whereKey($keys)->delete()),
])
->toolbarActions([   // grid-scoped buttons in the toolbar
    Action::make('new')->label('New Item')->url(fn () => route('items.create')),
])

Grid::make('resorts')
    ->query(fn () => Resort::query())
    ->authorize('resort.viewAny')
    ->exportable()                                    // csv + xlsx + pdf (the config default set)
    // ->exportable(['csv', 'xlsx'])                  // or exactly these formats
    // ->exportable(['csv'], fileName: 'resorts', limit: 10000)

use App\Models\Voucher;
use LaraGrid\Columns\{DateColumn, DecimalColumn, SerialColumn, TextColumn};
use LaraGrid\Grid;
use LaraGrid\Livewire\WithLaraGrid;
use Livewire\Component;

class DayBook extends Component
{
    use WithLaraGrid;

    /** Rows built for the normal in-memory screen. */
    public array $rows = [];

    public string $from = '';
    public string $to = '';

    protected function grids(): array
    {
        return ['dayBook' => $this->dayBookGrid()];
    }

    protected function dayBookGrid(): Grid
    {
        return Grid::make('dayBook')
            ->authorize(fn () => $this->authorize('viewAny', Voucher::class))
            ->exportRows(fn (array $state): iterable => $this->dayBookExportRows($state))
            ->exportable(['csv', 'xlsx', 'pdf'], fileName: 'day-book')
            ->columns([
                SerialColumn::make(),
                DateColumn::make('date')->sortable(),
                TextColumn::make('type')->sortable(),
                TextColumn::make('voucher')->sortable(),
                TextColumn::make('ledger'),
                DecimalColumn::make('debit')->scale(2),
                DecimalColumn::make('credit')->scale(2),
            ]);
    }

    /**
     * $state is exactly {sort, dir, search, filters}; unknown client keys and invalid
     * sort/filter targets have already been removed. Apply the intents your report supports.
     */
    protected function dayBookExportRows(array $state): iterable
    {
        // Component report filters such as $this->from/$this->to are already trusted server
        // state on this rehydrated Livewire component. Re-query and transform independently.
        foreach ($this->reportBuilder($this->from, $this->to)->lazyEntries() as $voucher) {
            foreach ($this->movePartyEntryFirst($voucher) as $row) {
                yield $row; // generators keep the export pipeline bounded-memory
            }
        }
    }

    public function render()
    {
        return view('livewire.day-book');
    }
}

// A service provider:
app(\LaraGrid\Export\ExporterRegistry::class)->register('pdf', new BrandedDompdfExporter);
app(\LaraGrid\Export\ExporterRegistry::class)->register('ods', new OdsExporter);

// A grid:
->exportable(['csv', 'ods'])     // unknown names still fail loudly at build time

Grid::make('resorts')
    ->query(fn () => Resort::query())
    ->authorize('resort.viewAny')
    ->savedViews()                    // opt-in; ->savedViews('key') overrides the storage key

Grid::make('items')
    ->query(fn () => Item::query())
    ->authorize('item.viewAny')
    ->persistQuery()                  // opt-in; ->persistQuery('session', 'key') overrides the key
    ->persistWidths()                 // composes — different lifetime, different state

->persistQuery(key: "items:{$companyId}")

$this->forgetGridQuery('items');      // no-op on a grid without ->persistQuery()

Grid::make('items')->theme('blue')        // per grid (unknown names fail loud at build time)

// config/laragrid.php — app-wide default; any grid's ->theme() overrides it
'theme' => 'emerald',

// A custom column type is just a class:
class RatingColumn extends \LaraGrid\Columns\Column
{
    public function painterId(): string { return 'rating'; }
    public function editorId(): ?string { return 'rating'; }
    public function parseSpec(): array { return ['kind' => 'int']; }
}

// App-specific formatters and parse kinds register in a service provider:
app(\LaraGrid\Formatting\FormatRegistry::class)->register('inr', new InrFormatter);
app(\LaraGrid\Casting\CastRegistry::class)->register('paise', new PaiseCast);

Livewire::test(BookingEntry::class)
    ->call('gridOps', 'lines', ['ops' => [
        ['t' => 'set', 'seq' => 1, 'row' => $key, 'col' => 'nights', 'v' => '3'],
    ]])
    ->call('gridAction', 'resorts', 'delete', [$id]);
bash
php artisan migrate
bash
php artisan vendor:publish --tag=laragrid-config      # config/laragrid.php (global defaults)
php artisan vendor:publish --tag=laragrid-views       # blade views (mount + badge/edit-link cells)
php artisan vendor:publish --tag=laragrid-assets      # copy dist/ to public/vendor/laragrid
php artisan vendor:publish --tag=laragrid-migrations  # the saved-views table migration (auto-loads otherwise)
blade
<x-laragrid :grid="$this->gridDefinition('resorts')" />
blade
{{-- These rows remain the in-memory display source; downloads never trust them. --}}
<x-laragrid :grid="$this->gridDefinition('dayBook')" :rows="$rows" />