0

In the puppeteer api docs an ElementHandle is defined:

ElementHandle represents an in-page DOM element. ElementHandles can be created with the page.$ method.

So given an ElementHandle I should be able to do all the basic functions you can do with the page: .click, .$$, .$x, .hover, etc

The same doc defines page.$x(expression)

expression <string> expression to evaluate (Xpath Expression)
returns: <Promise<Array<ElementHandle>>>

So I have the following that returns an array of ElementHandles:

const cameraRowList = await page.$x("//div[contains(@class, 'camera-row')]");

I actually get 5 items in the array as expected. So I need to loop through this list and check the ElementHandles for an svg object that has the id='locationChecked'. Then click it if it does. (all but the 4th one has this id currently)

for (const cameraRow of cameraRowList) {
   const [cameraHasLocation] = await cameraRow.$x("//div[@class='hasLocation']//*[@id='locationChecked']");
   if (cameraHasLocation) {
      const [cameraSelectBox] = await cameraRow.$x("//div[contains(@class, 'checkbox')]");
      await cameraSelectBox.click();
   }
}

The problem is two fold.

First: When it loops through the 5 ElementHandles in the Array, it always finds/evaluates the 'locationChecked' object, even when on the 4th it is not there.

Second: when it executes the cameraSelectionBox.click(); It always click the first one.

This tells me that it's probably ignoring the scope of the ElementHandle and using the entire page instead. and then executing on the first one it finds for each pass of the array.

What can i do to ensure the scope stays within the ElementHandle being used?

4

1 回答 1

0

我想到了。问题出在我的 xpath 上。

const [cameraHasLocation] = await cameraRow.$x("//div[@class='hasLocation']//*[@id='locationChecked']");

我应该使搜索相对“。/”我使用忽略 elementHandle 范围的全局“//”:

const [cameraHasLocation] = await cameraRow.$x("./div[@class='hasLocation']//*[@id='locationChecked']");
于 2020-01-22T17:26:24.783 回答