Skip to main content
Tutorial Free

Filament: Export Record to PDF - Two Ways

June 29, 2023
3 min read

Exporting data to PDF is a very common feature. This tutorial will show how to do it in the Filament admin panel: we will export a single record to PDF using Blade View and barryvdh/laravel-dompdf package.

PDF export action button

We will use the official Filament demo project for the demo code, adding a PDF download to the OrderResource. The source code for the original demo it can be found on the GitHub here.


Method 1: Filament Action

First, let's see how we can export into a PDF from Filament action.

app/Filament/Resources/Shop/OrderResource.php:

use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Support\Facades\Blade;
 
class OrderResource extends Resource
{
// ...
 
public static function table(Table $table): Table
{
return $table
->columns([
// ...
])
->filters([
// ...
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\Action::make('pdf')
->label('PDF')
->color('success')
->icon('heroicon-s-download')
->action(function (Model $record) {
return response()->streamDownload(function () use ($record) {
echo Pdf::loadHtml(
Blade::render('pdf', ['record' => $record])
)->stream();
}, $record->number . '.pdf');
}),
])
->bulkActions([
// ...
]);
}
 
// ...
}

The first import code here is what we return. This response comes from the Livewire where first we pass the content and the second parameter is the filename.

For the PDF content, we use the loadHTML method from the barryvdh/laravel-dompdf package, and we stream it. To get the HTML we are using the Blade facade to render the Blade file and passing the data.

After this, we have a PDF button in the Orders list.

PDF export action button

Now, in the Blade file, you can add any data you need about the record. I called this View pdf.blade.php.

resources/views/pdf.blade.php:

<div>Number: {{ $record->number }}</div>
<div>Customer: {{ $record->customer->name }}</div>
<div>Status: {{ $record->status }}</div>
<div>Total price: {{ $record->total_price }}</div>
<div>Order Date: {{ $record->created_at }}</div>

After clicking the PDF button, the PDF will be downloaded with basic information about the order.

PDF view


Method 2: Using Controller and Route

Here's an alternative approach. First, we need a Controller and a Route.

php artisan make:controller PdfController

routes/web.php:

use App\Http\Livewire\Form;
use App\Http\Controllers\PdfController;
 
\Illuminate\Support\Facades\Route::get('form', Form::class);
 
Route::get('pdf/{order}', PdfController::class)->name('pdf');

In the Controller, we can generate the PDF from the View using loadView method from the barryvdh/laravel-dompdf package and chaining it to download.

app/Http/Controllers/PdfController.php:

use App\Models\Shop\Order;
use Barryvdh\DomPDF\Facade\Pdf;
 
class PdfController extends Controller
{
public function __invoke(Order $order)
{
return Pdf::loadView('pdf', ['record' => $order])
->download($order->number. '.pdf');
}
}

We need to call this Route in the Filament action.

app/Filament/Resources/Shop/OrderResource.php:

class OrderResource extends Resource
{
// ...
 
public static function table(Table $table): Table
{
return $table
->columns([
// ...
])
->filters([
// ...
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\Action::make('pdf')
->label('PDF')
->color('success')
->icon('heroicon-o-document-download')
->url(fn (Order $record) => route('pdf', $record))
->openUrlInNewTab(),
])
->bulkActions([
// ...
]);
}
 
// ...
}

And that's it. After clicking the PDF button, it will open the URL in a new tab and will download the generated PDF file.


If you want more Filament examples, you can find more real-life projects on our FilamentExamples.com.

Enjoyed This Tutorial?

Get access to all premium tutorials, video and text courses, and exclusive Laravel resources. Join our community of 10,000+ developers.

Recent Courses on Laravel Daily

Laravel 13 Starter Kit Teams and Customizations

10 lessons
33 min

Laravel 13 Eloquent: Expert Level

41 lessons
1 h 34 min

Queues in Laravel 13

18 lessons
1 h 12 min read
szopenek17 avatar

Hello, First method deletes the template view for pdf from resource. Why ?

Nerijus avatar

deleteCachedView isn't needed

szopenek17 avatar

Yeah i know but from "Also, we don't need this cached View, so we are setting it to be deleted." It means cached view. So why it deletes my orginal template from resources/views/pdf.blade.php ?

Nerijus avatar

It was a mistake. Updated text.

👍 1
nikonachev avatar

This is a very helpful topic. In my case I use method 1: Filament Action. How can I use JavaScript in loaded Blade? I have this simple Blade template:

Test PDF

When I execute the code explained in Method 1 in the generated PDF is outputted “Test PDF” instead “I have changed!”. Where is my mistake and how to solve this problem? Thank you.

nikonachev avatar

Test PDF

Nerijus avatar

I guess then you cant? Would would you even want to use it?

nikonachev avatar

I want to use JavaScript to insert dynamically HTML using insertAdjacentHTML() but DomPdf does not take in account the JavaScript contained in the blade Template. And also I don’t know why I can’t paste in the comments the source of the Blade.

Nerijus avatar

If its dompdf thing cant help

nikonachev avatar

OK. Thank you.

Khairul Imran avatar

How to view pdf in browser without download it?

Modestas avatar

Change ->download(...) to ->stream(...) and it should work

Khairul Imran avatar

Nice. It work. Tq

Marco Garcia avatar

Hello and if I would like to open a modal with the pdf file what could you suggest me?

Modestas avatar

If you want a modal with the PDF, you do need:

https://laraveldaily.com/post/filament-table-row-action-view-modal-infolist

Or in other words, your modal has to be an infolist and there you have to create a custom HTML component (ViewEntry) to load the PDF in an iframe. There is no other way at this point

EmJay646 avatar

How can i pass the pdf to the ViewEntry? viewData does not accept a closure?

Domingo Añez avatar

With filamentphp v3, Laravel 10.34.2, PHP 8.2.0 I get the following error: Unable to prepare route [pdf/{record}] for serialization. Another route has already been assigned name [pdf]. in web.php: Route::get('pdf/{record}', PdfController::class)->name('pdf');

In PdfResourse.php Action::make(('Pdf')) ->icon('heroicon-o-printer') ->url(fn (Invoices $record) => route('pdf', $record)) ->openUrlInNewTab(),**

How do I resolve the routing error? *

Michal “Spil” Korol avatar
Michal “Spil” Korol

if its only name issue, just change route name ->name('another_pdf')

also refactor your code where you use routes by names

Yordanis Martinez avatar

I have used method 1. How can I add a custom CSS and JS file to my pdf.blade.php template?

Nerijus avatar

You can't add js and you shouldn't. As for CSS write a custom styles

Vito avatar

How do I customize the appearnace of the exported PDF?

For example: I wish to add my company logo and move around some of the locations of each field. A result would be a nice looking customer facing Invoice.

Modestas avatar

Since this is a view based PDF - you have to modify the view template itself. Anything you put inside of it - will be in your PDF.

We don't have a tutorial for this, as it is as simple as creating the HTML content

Kasper Nowak avatar

Does this also work for table header actions, or only for row actions?

I need to export/print a pdf of an admin panel resource table.

Modestas avatar

This should work on header action too

Denis Hancock avatar

It would be interesting to see how everyone does this not on a record but on the resultant table in filament. IE if you have a table that's the result of search or filter, how can you STREAM that to a PDF - Thanks for thoughts

Nerijus avatar

You would get selected records from the table component. Plenty of such questions on the filament discord, should check their

Denis Hancock avatar

Thanks

Javaabu avatar

Using the controller method, how can I make sure that the route is protected with the same authentication as the Filament portal? That seems like something very important that should be implemented.

Nerijus avatar

It's laravel. Add authorization in whate way you want