How can I render a PDF using a Livewire component that implements HasInfolists?

I've built an abstract component called App\Livewire\Pdf\Pdf . This component implements HasInfolists and HasForms.
abstract class Pdf extends Component implements HasForms, HasInfolists
{
use InteractsWithForms;
use InteractsWithInfolists;

#[Locked]
public mixed $record = [];

public function render(): View
{
return view(static::$view, $this->getRecord())
->layout(static::$layout, [
'title' => static::getTitle(),
]);
}

public function open(): Response
{
$pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView(static::$view, ['record' => $this->getRecord()]);

return $pdf->stream();
}
}
abstract class Pdf extends Component implements HasForms, HasInfolists
{
use InteractsWithForms;
use InteractsWithInfolists;

#[Locked]
public mixed $record = [];

public function render(): View
{
return view(static::$view, $this->getRecord())
->layout(static::$layout, [
'title' => static::getTitle(),
]);
}

public function open(): Response
{
$pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView(static::$view, ['record' => $this->getRecord()]);

return $pdf->stream();
}
}
This component is being used as an abstract class for App\Livewire\Pdf\MembershipAgreement. The class has its own blade file and headerInfolist method.
class MembershipAgreement extends Pdf
{
use HasMembershipInfolistSchema;
use HasMembershipPlanInfolistSchema;

protected static string $view = 'livewire.pdf.membership-agreement';

protected static string $layout = 'components.layouts.app';

public function headerInfolist(Infolist $infolist): Infolist
{
return $infolist
->record($this->getRecord())
->schema([
$this->getPlanTextEntry()
])
}
class MembershipAgreement extends Pdf
{
use HasMembershipInfolistSchema;
use HasMembershipPlanInfolistSchema;

protected static string $view = 'livewire.pdf.membership-agreement';

protected static string $layout = 'components.layouts.app';

public function headerInfolist(Infolist $infolist): Infolist
{
return $infolist
->record($this->getRecord())
->schema([
$this->getPlanTextEntry()
])
}
I have successfully created a rendered HTML file that routed to {base_url}/pdf/agreement/membership/{record}, using a typical render method. But when I tried to plug it in to \Barryvdh\DomPDF\Facade\Pdf, it throws an exception. In routes/web.php:
Route::name('membership.open')
->get('pdf/agreement/membership/{record}/open', [\App\Livewire\Pdf\MembershipAgreement::class, 'open']);
Route::name('membership.open')
->get('pdf/agreement/membership/{record}/open', [\App\Livewire\Pdf\MembershipAgreement::class, 'open']);
This is how the error looks: https://flareapp.io/share/67OwQOJ7 Thank you for reading to this point. Please let me know if this problem comes from me, Livewire, or barryvdh/laravel-dompdf.
Flare
Using $this when not in object context - The error occurred at https://dashboard.marsgym.test/pdf/agreement/membership/01hcye30x3nazdb1danprd728p/open
4 Replies
Anish
Anish10mo ago
Did you solve the problem? I am also trying a similar process but so far no luck
lazywaterpark
lazywaterparkOP10mo ago
I haven’t solved the issue. I just render the page and explicitly ask the users to hit Ctrl+P to print from the browser ¯\_(ツ)_/¯
Tieme
Tieme10mo ago
@lazywaterpark if you change $this-> to $record-> in blade file, what happens than? Like
@php

$firstPageInfolists = $record->getFirstPageInfolists();

$signatures = $record->getSignatures();

@endphp
@php

$firstPageInfolists = $record->getFirstPageInfolists();

$signatures = $record->getSignatures();

@endphp
Anish
Anish10mo ago
This is what works for me. I am developing a student application system, where student fill up the application, make payment for application fee and finally submit the application form. Once an application is submitted, we need to generate the pdf version of the application, save it to the disk and send it by email as attachment. So that is the context. I made liveware component - this is only to generate the application pdf (not for showing to the student)
class ApplicantForm extends Component
{

protected Application $application;


public function __construct(public int $applicationNo)
{
$this->mount();
}

public function mount(): void
{

$this->application = Application::firstWhere(
'application_no',
$this->applicationNo
)
->loadApplicationViewRelation();
}

public function applicationFormInfolist(Infolist $infolist): Infolist
{

return $infolist
->record($this->application)
->schema([ (new ApplicationFormPrintViewInfolist)() ]);
}

public function toHtml() : string
{
$infolist = Infolist::make($this);
return $this->applicationFormInfolist($infolist)
->toHtml();
}

public function printPDF()
{
Pdf::view('print-pdf', ['html' => $this->toHtml()])
->save( $this->application->getPDFFormPath() );
}

}
class ApplicantForm extends Component
{

protected Application $application;


public function __construct(public int $applicationNo)
{
$this->mount();
}

public function mount(): void
{

$this->application = Application::firstWhere(
'application_no',
$this->applicationNo
)
->loadApplicationViewRelation();
}

public function applicationFormInfolist(Infolist $infolist): Infolist
{

return $infolist
->record($this->application)
->schema([ (new ApplicationFormPrintViewInfolist)() ]);
}

public function toHtml() : string
{
$infolist = Infolist::make($this);
return $this->applicationFormInfolist($infolist)
->toHtml();
}

public function printPDF()
{
Pdf::view('print-pdf', ['html' => $this->toHtml()])
->save( $this->application->getPDFFormPath() );
}

}
I am using Spatie's PDF facade. This seems to work quite well with the CSS. The blade file is at this moment
<div>
{!! $html !!}
</div>
<div>
{!! $html !!}
</div>
I can use tinker to open a session and use
$appNo = 20240000001;
$pdf = new ApplicantForm($appNo);
$pdf->printPDF();
$appNo = 20240000001;
$pdf = new ApplicantForm($appNo);
$pdf->printPDF();
I have not yet taken the CSS, but this gets the data and creates a PDF file with correct data. This should be good enough for me. I hope that this helps. I have tested it out, with proper css. It works quite well.
Want results from more Discord servers?
Add your server