how make upload file button in header table list resource.
I want to make xls import button to database. ??
5 Replies
Maybe check the existing import plugin(s)
This is how I built an xls upload to import records into a Members table via a header action button in my MembersResource:
And the custom import Action:
And add the button to the List page header:
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';
}
}
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();
});
}
}
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'),
];
}
}
@DrByte thank bro.
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.