18

This is how I currently get each DOM property from an ElementHandle :

 let section: ElementHandle = await page.waitForSelector(".selector-list li");
 let tagName = await section.$eval('a', (e) => e.tagName);

But here it's tagName. What if I'd like want to inspect further properties ?

I don't want to write $eval for each property.

Question:

How can I convert ElementHandle to a Dom object , so I'd be able to browse all properties ? I want to get A as a Dom object.

Mir-Ismaili
  • 13,974
  • 8
  • 82
  • 100
Royi Namir
  • 144,742
  • 138
  • 468
  • 792
  • I'm sorry off topic, the let selection: syntax is confusing to me as I've not seen it before. Can someone point to what type of LET this is? I only know LET as a variable definition and the : is new to me. – Hellonearthis Oct 30 '18 at 22:33
  • @Hellonearthis it's typescript. the `:` is not mandatory , but it lets you have a seatbelt while programming ( not runtime). so this will cause error in compilation time : `let a:string=3` – Royi Namir Oct 31 '18 at 06:10
  • Thanks @Eris I see it's the way TS does type safety. – Hellonearthis Oct 31 '18 at 09:58

2 Answers2

9

Use ElementHandle.evaluate():

const elementHandle = await page.waitForSelector('.selector-list li')

elementHandle.evaluate((domElement) => {
    domElement.tagName  
    // etc ...
})

Typescript:

const elementHandle: ElementHandle = await page.waitForSelector('.selector-list li')

elementHandle.evaluate((domElement) => {
    domElement.tagName  
    // etc ...
})
Mir-Ismaili
  • 13,974
  • 8
  • 82
  • 100
  • 1
    You will need to also add a generic type to the `ElementHandle` or else the access to `domElement.tagName` will cause a type error, since it will only have access to attributes of the TypeScript `Element` interface. For example, I had to use `elementHandle.evaluate()` to access the `value` attribute of an `` element. To get around the type error, I did `const elementHandle: ElementHandle = ...`, which is legal because `HTMLInputElement` is a descendent of `Element`. – ecbrodie Dec 08 '20 at 04:35
8

The better way would be to execute the code on the page via page.evaluate and return the results. That way you can return an array with values:

const result = await page.evaluate(() => {
    const elements = document.querySelectorAll(".selector-list li");
    // do something with elements, like mapping elements to an attribute:
    return Array.from(elements).map(element => element.tagName);
});

result will then be an array with the attribute values of tagName of each element.

Thomas Dondorf
  • 23,416
  • 6
  • 84
  • 105