Atav32
Atav32

Reputation: 1812

How does an ElementHandle differ from a DOM Element?

The documentation on page.$(selector) says it returns a promise containing an ElementHandle.

But the documentation on ElementHandle is a bit lacking.

It says it "represents a DOM element", but what does that really mean? And if does represent the DOM, why can't the contents of the ElementHandle be inspected?

It also says, "prevents DOM element from garbage collection unless the handle is disposed." Why would a DOM element get garbage collected if the browser is still on the page?


This came up because I thought it'd be simple to grab the text from an element on the page, so I tried,

const text = await page.$('#text').textContent;

which returned undefined. So I tried,

const text = await page.$('#text').textContent();

which threw an error.

Turns out the correct way is

const text = await page.evaluate(() => document.querySelector('#text').textContent);

Upvotes: 17

Views: 6611

Answers (1)

Everettss
Everettss

Reputation: 16029

With ElementHandle can you still access to properties like textContent but in "Puppeteer way". Firstly you must .getProperty() on ElementHandle, and after that convert it to .jsonValue(). Remember that all this operations returns poromises so you should await on all of them like this:

await (await (await page.$('#text')).getProperty('textContent')).jsonValue();

Here is full working example:

const puppeteer = require('puppeteer');

const html = `
<html>
  <body>
    <div id="text">Sample content</div>
  </body>
</html>`;

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto(`data:text/html,${html}`);

  const text = await page.evaluate(() => document.querySelector('#text').textContent);
  const text2 = await (await (await page.$('#text')).getProperty('textContent')).jsonValue();

  console.log(text);
  console.log(text2);

  await browser.close();
})();

Upvotes: 10

Related Questions