F
Filament14mo ago
arul

how make upload file button in header table list resource.

I want to make xls import button to database. ??
5 Replies
Dennis Koch
Dennis Koch14mo ago
Maybe check the existing import plugin(s)
DrByte
DrByte14mo ago
This is how I built an xls upload to import records into a Members table via a header action button in my MembersResource: composer require maatwebsite/excel Created the excel importer:
class MembersImport implements ToModel, WithHeadingRow, WithValidation, SkipsOnFailure, WithUpserts
{
use Importable;
use SkipsFailures;

public function model(array $row): ?Member
{
// map model fields to spreadsheet rows by column name
return new Member([
'company_name' => $row['organization'],
'name' => $row['first_name'] . ' ' . $row['last_name'],
'email' => $row['email'],
'phone' => $row['phone'],
]);
}

// rows must contain an email address, not blank
public function rules(): array
{
return [
'*.email' => ['required', 'email'],
];
}

// Rows with matching email already in db will be ignored.
public function uniqueBy(): string|array
{
return 'email';
}
}
class MembersImport implements ToModel, WithHeadingRow, WithValidation, SkipsOnFailure, WithUpserts
{
use Importable;
use SkipsFailures;

public function model(array $row): ?Member
{
// map model fields to spreadsheet rows by column name
return new Member([
'company_name' => $row['organization'],
'name' => $row['first_name'] . ' ' . $row['last_name'],
'email' => $row['email'],
'phone' => $row['phone'],
]);
}

// rows must contain an email address, not blank
public function rules(): array
{
return [
'*.email' => ['required', 'email'],
];
}

// Rows with matching email already in db will be ignored.
public function uniqueBy(): string|array
{
return 'email';
}
}
And the custom import Action:
namespace App\Filament\Admin\Resources\MemberResource\Actions;

use App\Imports\MembersImport;
use Filament\Actions\Action;
use Filament\Forms;

class MemberImportAction extends Action
{
public static function getDefaultName(): ?string
{
return 'import';
}

protected function setUp(): void
{
parent::setUp();

$this->label('Import Members');
$this->modalHeading('Import Members');
$this->modalSubmitActionLabel('Import File');
$this->icon('heroicon-s-arrow-up-tray');
$this->successNotificationTitle('Import completed.');

$this->form([
Forms\Components\FileUpload::make('filename')
->label('Members spreadsheet file')
->helperText("Supported file types include: XLXS, XLS, CSV. The 'email' column must not be blank. Duplicate emails will be ignored.")
->acceptedFileTypes(['xls','xlsx', 'csv', 'text/csv', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'])
->storeFiles(false)
->visibility('private')
->preserveFilenames()
->required(),
]);

$this->action(function (): void {
$file = $this->getFormData()['filename'];

$import = new MembersImport;
$import->import($file);

$failures = $import->failures();

foreach ($failures as $failure) {
// TODO: display which records failed to import
}
// TODO: display the errors in failureNotification() or maybe a modal

$this->sendSuccessNotification();
$this->success();
});
}
}
namespace App\Filament\Admin\Resources\MemberResource\Actions;

use App\Imports\MembersImport;
use Filament\Actions\Action;
use Filament\Forms;

class MemberImportAction extends Action
{
public static function getDefaultName(): ?string
{
return 'import';
}

protected function setUp(): void
{
parent::setUp();

$this->label('Import Members');
$this->modalHeading('Import Members');
$this->modalSubmitActionLabel('Import File');
$this->icon('heroicon-s-arrow-up-tray');
$this->successNotificationTitle('Import completed.');

$this->form([
Forms\Components\FileUpload::make('filename')
->label('Members spreadsheet file')
->helperText("Supported file types include: XLXS, XLS, CSV. The 'email' column must not be blank. Duplicate emails will be ignored.")
->acceptedFileTypes(['xls','xlsx', 'csv', 'text/csv', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'])
->storeFiles(false)
->visibility('private')
->preserveFilenames()
->required(),
]);

$this->action(function (): void {
$file = $this->getFormData()['filename'];

$import = new MembersImport;
$import->import($file);

$failures = $import->failures();

foreach ($failures as $failure) {
// TODO: display which records failed to import
}
// TODO: display the errors in failureNotification() or maybe a modal

$this->sendSuccessNotification();
$this->success();
});
}
}
And add the button to the List page header:
class ListMembers extends ListRecords
{
protected static string $resource = MemberResource::class;

protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),

MemberResource\Actions\MemberImportAction::make()
->visible(auth()->user()->hasRole('Super-Admin'))
->color('secondary'),
];
}
}
class ListMembers extends ListRecords
{
protected static string $resource = MemberResource::class;

protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),

MemberResource\Actions\MemberImportAction::make()
->visible(auth()->user()->hasRole('Super-Admin'))
->color('secondary'),
];
}
}
arul
arulOP14mo ago
@DrByte thank bro.
DrByte
DrByte12mo ago
Note: now Filament 3.1 has its own CSV Import feature. So, if it provides what you need already, then you can avoid adding the maatwebsite/excel package the way I did here.
Want results from more Discord servers?
Add your server