I'm trying to iterate over a list of dynamic elements with Playwright, I've tried a couple of things already, but none have been working:
await this.page.locator('li').click(); const elements = await this.page.locator('ul > li'); await elements.click() await this.page.$$('ul > li').click(); await this.page.click('ul > li'); const divCounts = await elements.evaluateAll(async (divs) => await divs.click()); this.page.click('ul > li > i.red', { strict: false, clickCount: 1 },) const elements = await this.page.$$('ul > li > i.red') elements.forEach(async value => { console.log(value) await this.page.click('ul > li > i.red', { strict: false, clickCount: 1 },) await value.click(); }) 5 Answers
Since doesn't have a good example on how to use .elementHandles().
Another way to solve this issue is as follows
const checkboxLocator = page.locator('tbody tr input[type="checkbox"]'); for (const el of await checkboxLocator.elementHandles()) { await el.check(); } I managed to do it with the following code:
test('user can click multiple li', async ({ page }) => { const items = page.locator('ul > li'); for (let i = 0; i < await items.count(); i++) { await items.nth(i).click(); } }) 2A similar question was asked recently on the Playwright Slack community. This is copy-pasted and minimally adjusted from the answer by one of the maintainers there.
let listItems = this.page.locator('ul > li'); // In case the li elements don't appear all together, you have to wait before the loop below. What element to wait for depends on your situation. await listItems.nth(9).waitFor(); for (let i = 0; i < listItems.count(); i++) { await listItems.nth(i).click(); } 4This works for me (my example):
// reset state and remove all existing bookmarks const bookmarkedItems = await page.locator('.bookmark img[src="/static/img/like_orange.png"]'); const bookmarkedItemsCounter = await bookmarkedItems.count(); if (bookmarkedItemsCounter) { for (let i = 0; i < bookmarkedItemsCounter; i++) { await bookmarkedItems.nth(i).click(); } } await page.waitForTimeout(1000); If try to solve your task should be:
test('click by each li element in the list', async ({ page }) => { await page.goto(some_url); const liItems = await page.locator('ul > li'); const liItemCounter = await liItems.count(); if (liItemCounter) { for (let i = 0; i < liItemCounter; i++) { await liItems.nth(i).click(); } } await page.waitForTimeout(1000); }); 1You can achieve that using $$eval and pure client side javascript.
const results = await page.$$eval(`ul > li`, (allListItems) => { allListItems.forEach(async singleListItem => await singleListItem.click()) }); Please note that what you write inside the callback, will be executed on the browser. So if you want to output anything, you need to return it. That way it will end up inside the results variable.