Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WireLinkColumn #76

Open
wants to merge 5 commits into
base: ReorderAndNewActions
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to `laravel-livewire-tables` will be documented in this file

## [v3.2.1] - 2023-02-19
### New Features
- Creation of new WireLink Column

## [v3.2.0] - 2023-01-04
### Tweaks
- Migration to new Core Traits, and de-duplication of code by @lrljoe in https://github.com/rappasoft/laravel-livewire-tables/pull/1623
Expand Down
35 changes: 35 additions & 0 deletions docs/columns/other-column-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,41 @@ LinkColumn::make('Action')
]),
```

## WireLinkColumn Columns

WireLink columns provide a way to display Wired Links in your table without having to use `format()` or partial views, with or without a Confirmation Message

WireLinkColumn requires title, and an "action", which must be a valid LiveWire method in the current class, or a global method

Without a Confirmation Message
```php
WireLinkColumn::make("Delete Item")
->title(fn($row) => 'Delete Item')
->action(fn($row) => 'delete("'.$row->id.'")'),
```

You may also pass a string to "confirmMessage", which will utilise LiveWire 3's "wire:confirm" approach to display a confirmation modal.

```php
WireLinkColumn::make("Delete Item")
->title(fn($row) => 'Delete Item')
->confirmMessage('Are you sure you want to delete this item?')
->action(fn($row) => 'delete("'.$row->id.'")')
->attributes(fn($row) => [
'class' => 'btn btn-danger',
]),
```

And you may also pass an array of attributes, which will be applied to the "button" element used within the Column
```php
WireLinkColumn::make("Delete Item")
->title(fn($row) => 'Delete Item')
->action(fn($row) => 'delete("'.$row->id.'")')
->attributes(fn($row) => [
'class' => 'btn btn-danger',
]),
```

## Button Group Columns

Button group columns let you provide an array of LinkColumns to display in a single cell.
Expand Down
9 changes: 9 additions & 0 deletions resources/views/includes/columns/wirelink.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<button
{!! count($attributes) ? $column->arrayToAttributes($attributes) : '' !!}
@if($column->hasConfirmMessage())
wire:confirm="{{ $column->getConfirmMessage() }}"
@endif
@if($column->hasActionCallback())
wire:click="{{ $path }}"
@endif
>{{ $title }}</button>
12 changes: 6 additions & 6 deletions src/Traits/Helpers/TableAttributeHelpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,47 +16,47 @@ public function getComponentWrapperAttributes(): array
}

/**
* @return array<mixed>
* @return array<mixed>
*/
public function getTableWrapperAttributes(): array
{
return count($this->tableWrapperAttributes) ? $this->tableWrapperAttributes : ['default' => true];
}

/**
* @return array<mixed>
* @return array<mixed>
*/
public function getTableAttributes(): array
{
return count($this->tableAttributes) ? $this->tableAttributes : ['id' => 'table-'.$this->getTableName(), 'default' => true];
}

/**
* @return array<mixed>
* @return array<mixed>
*/
public function getTheadAttributes(): array
{
return count($this->theadAttributes) ? $this->theadAttributes : ['default' => true];
}

/**
* @return array<mixed>
* @return array<mixed>
*/
public function getTbodyAttributes(): array
{
return count($this->tbodyAttributes) ? $this->tbodyAttributes : ['default' => true];
}

/**
* @return array<mixed>
* @return array<mixed>
*/
public function getThAttributes(Column $column): array
{
return $this->thAttributesCallback ? call_user_func($this->thAttributesCallback, $column) : ['default' => true];
}

/**
* @return array<mixed>
* @return array<mixed>
*/
public function getThSortButtonAttributes(Column $column): array
{
Expand Down
45 changes: 45 additions & 0 deletions src/Views/Columns/WireLinkColumn.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Views\Columns;

use Illuminate\Database\Eloquent\Model;
use Rappasoft\LaravelLivewireTables\Exceptions\DataTableConfigurationException;
use Rappasoft\LaravelLivewireTables\Views\Column;
use Rappasoft\LaravelLivewireTables\Views\Traits\Configuration\WireLinkColumnConfiguration;
use Rappasoft\LaravelLivewireTables\Views\Traits\Core\{HasActionCallback,HasConfirmation, HasTitleCallback};
use Rappasoft\LaravelLivewireTables\Views\Traits\Helpers\WireLinkColumnHelpers;

class WireLinkColumn extends Column
{
use WireLinkColumnConfiguration,
WireLinkColumnHelpers,
HasActionCallback,
HasTitleCallback,
HasConfirmation;

protected string $view = 'livewire-tables::includes.columns.wirelink';

public function __construct(string $title, ?string $from = null)
{
parent::__construct($title, $from);

$this->label(fn () => null);
}

public function getContents(Model $row): null|string|\Illuminate\Support\HtmlString|DataTableConfigurationException|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
{
if (! $this->hasTitleCallback()) {
throw new DataTableConfigurationException('You must specify a title callback for a WireLink column.');
}

if (! $this->hasActionCallback()) {
throw new DataTableConfigurationException('You must specify an action callback for a WireLink column.');
}

return view($this->getView())
->withColumn($this)
->withTitle(app()->call($this->getTitleCallback(), ['row' => $row]))
->withPath(app()->call($this->getActionCallback(), ['row' => $row]))
->withAttributes($this->hasAttributesCallback() ? app()->call($this->getAttributesCallback(), ['row' => $row]) : []);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Views\Traits\Configuration;

trait WireLinkColumnConfiguration
{
}
28 changes: 28 additions & 0 deletions src/Views/Traits/Core/HasActionCallback.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Views\Traits\Core;

use Closure;
use Rappasoft\LaravelLivewireTables\Views\{Column,Filter};

trait HasActionCallback
{
protected mixed $actionCallback = null;

public function action(callable $callback): self
{
$this->actionCallback = $callback;

return $this;
}

public function getActionCallback(): ?callable
{
return $this->actionCallback;
}

public function hasActionCallback(): bool
{
return $this->actionCallback !== null;
}
}
28 changes: 28 additions & 0 deletions src/Views/Traits/Core/HasConfirmation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Views\Traits\Core;

use Closure;
use Rappasoft\LaravelLivewireTables\Views\{Column,Filter};

trait HasConfirmation
{
protected ?string $confirmMessage;

public function confirmMessage(string $confirmMessage): self
{
$this->confirmMessage = $confirmMessage;

return $this;
}

public function hasConfirmMessage(): bool
{
return isset($this->confirmMessage);
}

public function getConfirmMessage(): string
{
return $this->confirmMessage;
}
}
7 changes: 7 additions & 0 deletions src/Views/Traits/Helpers/WireLinkColumnHelpers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Views\Traits\Helpers;

trait WireLinkColumnHelpers
{
}
59 changes: 59 additions & 0 deletions tests/Views/Columns/WireLinkColumnTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Tests\Views\Columns;

use Rappasoft\LaravelLivewireTables\Exceptions\DataTableConfigurationException;
use Rappasoft\LaravelLivewireTables\Tests\Models\Pet;
use Rappasoft\LaravelLivewireTables\Tests\TestCase;
use Rappasoft\LaravelLivewireTables\Views\Columns\WireLinkColumn;

class WireLinkColumnTest extends TestCase
{
/** @test */
public function can_set_the_column_title(): void
{
$column = WireLinkColumn::make('Name', 'name');

$this->assertSame('Name', $column->getTitle());
}

/** @test */
public function can_not_infer_field_name_from_title_if_no_from(): void
{
$column = WireLinkColumn::make('My Title');

$this->assertNull($column->getField());
}

/** @test */
public function can_not_render_field_if_no_title_callback(): void
{
$this->expectException(DataTableConfigurationException::class);

WireLinkColumn::make('Name')->getContents(Pet::find(1));
}

/** @test */
public function can_not_render_field_if_no_action_callback(): void
{
$this->expectException(DataTableConfigurationException::class);

WireLinkColumn::make('Name')->title(fn ($row) => 'Edit')->getContents(Pet::find(1));
}

/** @test */
public function can_render_field_if_title_and_action_callback(): void
{
$column = WireLinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn ($row) => 'delete("'.$row->id.'")')->getContents(Pet::find(1));

$this->assertNotEmpty($column);
}

/** @test */
public function can_render_field_if_confirm_set(): void
{
$column = WireLinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn ($row) => 'delete("'.$row->id.'")')->confirmMessage('Test')->getContents(Pet::find(1));

$this->assertNotEmpty($column);
}
}