Search code examples
laraveldompdf

Laravel barryvdh/laravel-dompdf multiple components of view in one pdf


I am using barryvdh/laravel-dompdf to generate pdf.

I'm trying generate one pdf file with multiple pages from data collection the problem is that I get only first element and one page. Using foreach loop to generate pages. Also I was trying to use foreach in my blade, but then I get only the last page.

Controller:
public function multiplePagesPdf(Request $request)
    {
            $kuponai = Kuponas::all();
            //dd($kuponas);
            $html = '';
            foreach($kuponai as $kuponas)
            {
                $view = view('pdf.multiple')->with(compact('kuponas'));
                $html .= $view->render();
            }
            $pdf = PDF::loadHTML($html);            
            $sheet = $pdf->setPaper('a4', 'landscape');
            return $sheet->stream('sugeneruoti.pdf');             

    }

Maybe problem in my blade file:

    <!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Dovanų kuponas</title>
</head>
<body>
  <div class="coupon">
    <div class="page">
      <div class="subpage">
        <div class="container" style="
              width: 21cm;
              height: 16cm;
              position: absolute;
              top: 6.8cm;
              font-family: DejaVu Sans;
              background: white;
            ">
         <h2>{{!! $kuponas->kupono_nr !!}}</h2>
          <h3 style="margin-left: 3.2cm">
            Dovanų kupono numeris:
            <span style="color: black"></span>
          </h3>
        </div>
      </div>
    </div>
  </div>
</body>

</html>
<style>
  @page {
    size: A4;
    margin: 0;
  }

  @media print {
    .page {
      margin: 0;
      border: initial;
      border-radius: initial;
      width: initial;
      min-height: initial;
      box-shadow: initial;
      background: initial;
      page-break-after: always;
    }
  }
</style>

Solution

  • There are certain things that are wrong in the code snippet you have provided, I will explain those first then provide correct way of doing it(for which I get results).

    • Firstly

    you have used with & compact together, I don't know if it gets correct results but you should use any one of them or use array syntax of view method.

    • Secondly

    what you are doing it you are rendering the view to html & then concating it, so , your html would look like,

    <html>
    .... content
    </html>
    <html>
    .... content
    </html>
    & so on.
    
    • Thirdly

    You css is messed up & not working as you want because of inline css you have added.

    Solution

    I would have used View Components to create similar views with different data. So we would create a component in resources/views/components/single.blade.php (here I have named it single). I have added your repeative code in the component single from your view. Now your coupon div class is in the component single.

    <div class="coupon">
        <div class="page">
          <div class="subpage">
            <div>
             <h2>{{ $kuponas->kupono_nr }}</h2>
              <h3>
                Dovanų kupono numeris:
                <span></span>
              </h3>
            </div>
          </div>
        </div>
      </div>
    

    Then in your view,

    <!DOCTYPE html>
    <html lang="en">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <head>
      <title>Dovanų kuponas</title>
      <style>
        .page-break {
        page-break-after: always;
    }
      </style>
    </head>
    <body>
      @php $count = 0;@endphp
      @foreach ($kuponai as $kuponas)
      @php $count++ @endphp
        <div class="container {{ (count($kuponai)-1 >= $count) ? 'page-break' : '' }}">
            @component('pdf.components.single', ['kuponas' => $kuponas])
            @endcomponent
        </div>    
      @endforeach
    </body>
    
    </html>
    
    

    use page-break class to create breaks, I have used count condition to remove one extra page break. I am passing the data of kuponas to the component.

    Finally change your controller,

    public function multiplePagesPdf(Request $request)
        {
            $kuponai = Kuponas::all();
            //dd($kuponas);
            
            $view = view('pdf.multiple', ['kuponai' => $kuponai]);
            $html = $view->render();
            $pdf = PDF::loadHTML($html)->setPaper('a4', 'landscape');            
            return $pdf->stream('sugeneruoti.pdf');
        }