如何程序化展开Combobox/Listbox并通过Span文本值选择选项?
解决ng-select组件程序化展开及选项选择问题
问题背景
我尝试在网站中展开一个combobox/listbox,目前在控制台执行以下代码可以通过指定Span文本选择对应选项,但必须先手动点击列表框使其展开后才能生效:
let countylocation = 'Cook County - Municipal Civil - District 2 - Skokie'; await page.evaluate((countylocation) => { Array.from(document.querySelectorAll('span')).filter(li => { return li.innerText == countylocation }).forEach(element => { if (element) element.click(); // click on il with specific text }); }, countylocation);
观察到点击前后控件的aria-expanded属性会变化,但尝试程序化点击指定元素或直接设置该属性时,均返回undefined错误:
尝试的点击代码
await page.evaluate(() => {document.querySelector("body > ngb-modal-window > div > div > app-case-search-filter-modal > div > form > div.modal-body > div > div > app-searchable-dropdown-field > div > div.form-group.ng-pristine.ng-invalid.ng-touched > div > span > ng-select > div > div > div.ng-input").click() });
尝试设置属性的代码
document.querySelector("body > ngb-modal-window > div > div > app-case-search-filter-modal > div > form > div.modal-body > div > div > app-searchable-dropdown-field > div > div.form-group.ng-pristine.ng-invalid.ng-touched > div > span > ng-select > div > div > div.ng-input").setAttribute('aria-expanded', 'true');
可行解决方案
1. 简化选择器并等待元素加载
绝对选择器过于脆弱,且可能元素未完全渲染就执行查询导致返回undefined。改用基于组件类的稳定选择器,同时用Puppeteer的waitForSelector确保元素可见:
// 等待ng-select下的输入框元素加载完成 await page.waitForSelector('ng-select .ng-input', { visible: true }); // 执行点击展开下拉 await page.evaluate(() => { document.querySelector('ng-select .ng-input').click(); });
2. 直接调用ng-select组件内置方法
如果是Angular的ng-select组件,可直接调用组件的open()方法展开下拉,无需模拟点击:
await page.evaluate(() => { const ngSelect = document.querySelector('ng-select'); if (ngSelect) { ngSelect.open(); } });
3. 模拟键盘事件触发展开
部分下拉组件支持通过空格键或向下箭头触发展开,可尝试此方式:
// 先聚焦到输入框,再按下空格键 await page.focus('ng-select .ng-input'); await page.keyboard.press('Space');
4. 直接通过组件API选择选项(无需提前展开)
可以跳过手动展开步骤,直接找到目标选项并通过组件API完成选择:
const countylocation = 'Cook County - Municipal Civil - District 2 - Skokie'; await page.evaluate((countylocation) => { const ngSelect = document.querySelector('ng-select'); if (ngSelect) { const targetOption = Array.from(ngSelect.querySelectorAll('ng-option')) .find(opt => opt.innerText.trim() === countylocation); if (targetOption) { ngSelect.select(targetOption); } } }, countylocation);
5. 处理模态框的异步加载逻辑
由于组件嵌套在ngb-modal-window模态框中,需先确保模态框完全初始化:
// 等待模态框可见 await page.waitForSelector('ngb-modal-window', { visible: true }); // 等待下拉组件输入框加载完成 await page.waitForSelector('ng-select .ng-input', { visible: true }); // 执行展开操作 await page.click('ng-select .ng-input');
内容的提问来源于stack exchange,提问作者user19157753
相关产品推荐
相关产品推荐

