Integrating Puppeteer with Angular: PDF Generation on Click

I’m working on a project that needs to create PDFs using Puppeteer in a Node.js backend and trigger this action from an Angular frontend. Here’s what I’ve got so far:

In my Node.js server, I have this Puppeteer code:

const webScraper = require('webScraper');

async function generatePDF() {
  const crawler = await webScraper.init();
  const webPage = await crawler.openPage();
  await webPage.navigate('/form_page.html', {waitForLoad: 'networkIdle'});
  await webPage.savePDF({destination: 'output/result.pdf', pageSize: 'Letter'});
  crawler.shutdown();
}

I want to call this function when a user clicks a button in my Angular app. I’ve tried setting up a controller like this:

$scope.createDocument = function() {
  $http.get('/generate-pdf')
    .then(function(response) {
      $scope.result = response.data;
    })
    .catch(function(error) {
      console.error('Failed:', error);
    });
};

And on my server:

app.get('/generate-pdf', function(req, res) {
  generatePDF();
  res.send('PDF created');
});

But I’m not sure if this is the right approach. How can I properly connect the Puppeteer function to an ng-click event in Angular? Any tips on best practices for this kind of setup?

Your approach is on the right track, but there are a few improvements we can make. First, consider using a POST request instead of GET for generating PDFs, as it’s more suitable for actions that change server state. Also, it’s a good practice to make your server-side function asynchronous.

Here’s how you could refactor your server code:

app.post('/generate-pdf', async (req, res) => {
  try {
    await generatePDF();
    res.status(200).json({ message: 'PDF created successfully' });
  } catch (error) {
    res.status(500).json({ error: 'Failed to generate PDF' });
  }
});

In your Angular component, update the method to use POST:

createDocument() {
  this.http.post('/generate-pdf', {}).subscribe(
    (response) => console.log('PDF generated'),
    (error) => console.error('Error:', error)
  );
}

This setup provides better error handling and follows RESTful principles more closely. Remember to add appropriate loading indicators and error messages in your UI for a better user experience.

I’ve actually implemented a similar feature in one of my projects. One thing I’d suggest is to consider sending the PDF back to the client instead of just a confirmation message. This way, you can offer immediate download or preview.

Here’s a rough idea of how you could modify your server code:

app.get('/generate-pdf', async (req, res) => {
  const pdfBuffer = await generatePDF();
  res.contentType('application/pdf');
  res.send(pdfBuffer);
});

Then in your Angular controller:

$scope.createDocument = function() {
  $http.get('/generate-pdf', { responseType: 'arraybuffer' })
    .then(function(response) {
      var file = new Blob([response.data], { type: 'application/pdf' });
      var fileURL = URL.createObjectURL(file);
      window.open(fileURL);
    })
    .catch(function(error) {
      console.error('Failed:', error);
    });
};

This approach allows for a smoother user experience. Just remember to handle potential errors and add appropriate loading indicators.

hey mate, i’ve done something similar before. instead of using $http.get, try $http.post and send any necessary data. on the server side, use app.post and make the generatePDF function async. wait for it to finish before sending the response. like this:

app.post(‘/generate-pdf’, async (req, res) => {
await generatePDF();
res.send(‘PDF created’);
});

hope this helps!