Pipo
Pipo

Reputation: 5611

puppeteer : set a dropdown option as selected based on text in an external function

Because I dont find puppeteer native function for set a dropdown option as selected based on text and not on value, I am tryiong to write it by myself

async function setSelectName(page, selector, valText) {
   return await page.evaluate((data) => {
       console.log(JSON.stringify(data));

       let options = document.querySelectorAll(data.selector);
       console.log(JSON.stringify(options));

       let optionCount = options.length;

       for (let i = 0; i < optionCount; ++i) {
           if (options[i].text === data.valText) {
               console.log('match');
                document.querySelector(data.selector).value = options[i].value;
           }
       }

   }, {selector, valText})
}

Unfortunately it does not work, and when i try to display selected options in console it displays me:

{"0":{"0":{},"1":{},"2":{},"3":{}}}

Do understand what happens and how to do it?

Upvotes: 2

Views: 4859

Answers (3)

Pipo
Pipo

Reputation: 5611

async function selectOptionByText(page, seletctId, textWanted) {

   const optionWaned = (await page.$x(`//*[@id = "${seletctId}"]/option[text() = "${textWanted}"]`))[0];

   const opionValue = await (await optionWaned .getProperty('value')).jsonValue();

   await page.select(`#${seletctId}`', opionValue );
}

Upvotes: 2

sharkdawg
sharkdawg

Reputation: 984

You are not actually selecting the text, try something like the following

let options = Array.from(document.querySelectorAll(data.selector)).map(option => option.innerText)

Upvotes: 1

Kayce Basques
Kayce Basques

Reputation: 25947

It's not the most intuitive workflow. Here's a working Glitch example of scraping a page to get the name attribute of a select node.

https://glitch.com/edit/#!/puppeteer-queryselector-eval-example

server.js:

const express = require('express'),
    app = express(),
    puppeteer = require('puppeteer');

app.use(express.static('public'));

app.get("/", async (request, response) => {
  try {
    const browser = await puppeteer.launch({
      args: ['--no-sandbox']
    });
    const page = await browser.newPage();
    await page.goto('https://sleet-dagger.glitch.me/cars.html');
    const selector = 'select';
    const name = await page.$eval(selector, node => node.name);
    response.send(name);
    await browser.close();
  } catch (error) {
    response.status(503).end(error.message);
  }
});

var listener = app.listen(process.env.PORT, function () {
  console.log('Your app is listening on port ' + listener.address().port);
});

cars.html:

<!DOCTYPE html>
<html>
<body>

<select name="bingo">
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="opel">Opel</option>
  <option value="audi">Audi</option>
</select>

</body>
</html>

The key is const name = await page.$eval(selector, node => node.name), which runs document.querySelector(selector) on the page, and then passes the node to the callback function in the second argument. See also:

I think that should be enough to get you on your way. Good luck!

Upvotes: 1

Related Questions