0

how to traverse all tr to give values in td.In my code it is overriding same tr/td.

My table.

#qty to add
<tbody id="gridview-1161-body">
<tr id="gridview-1161-record-19842148" data-boundview="gridview-1161" class="x-grid-row x-grid-data-row" tabindex="-1">
<td role="gridcell" class="x-grid-cell x-grid-td x-grid-cell-headerId-gridcolumn-1158  rp-grid-editable-cell  rp-grid-editable-cell" id="ext-gen2535">
<div class="x-grid-cell-inner " style="text-align:right;">
<div class="rp-invalid-cell rp-icon-alert-require-field">
</div>
<input id="numberfield-1243-inputEl" type="text" role="spinbutton" name="Quantity" class="x-form-field x-form-text x-form-focus x-field-form-focus x-field-default-form-focus" autocomplete="off" style="width: 100%;"> 
</div></td>
</tr>

same like 
<tr>..</tr></tbody>

Here all the id's are dynamically generating via code. My python code:

#add qty
    rowCount=len(driver.find_elements_by_xpath("//tbody[@id='gridview-1161-body']/tr"));
    print(rowCount)
    for row in rowCount:
        element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "td.x-grid-cell.x-grid-td.rp-grid-editable-cell[role='gridcell']")))
        element.click()
        time.sleep(2)

        #input box to give qty-working for this id
        driver.find_element(By.ID, "numberfield-1243-inputEl").send_keys('10')
        driver.find_element(By.ID, "numberfield-1243-inputEl").send_keys(Keys.ENTER)

due to dynamic id i can't give find_element(By.ID)So i am using CSS_SELECTOR to find the td,but it is overriding same td..how to give tr.next to traverse all tr in table ?

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
Divya Mani
  • 203
  • 1
  • 3
  • 15

3 Answers3

1

To handle dynamic ID Induce WebDriverWait() and visibility_of_all_elements_located() and Following XPATH option.

driver=webdriver.Chrome()
rows=WebDriverWait(driver,15).until(EC.visibility_of_all_elements_located((By.XPATH,"//tbody[contains(@id,'-body')]//tr[@class='x-grid-row x-grid-data-row']")))
for rownum in range(len(rows)):

     #To avoid stale exception re-assign rows elements again
     rows = WebDriverWait(driver, 10).until(EC.visibility_of_all_elements_located((By.XPATH, "//tbody[contains(@id,'-body')]//tr[@class='x-grid-row x-grid-data-row']")))
     element=rows[rownum].find_element_by_xpath(".//td[contains(@class,'rp-grid-editable-cell  rp-grid-editable-cell') and @role='gridcell']")
     element.click()
     input=rows[rownum].find_element_by_xpath(".//input[@name='Quantity' and @role='spinbutton']")
     input.send_keys('10')
     input.send_keys(Keys.ENTER) 
KunduK
  • 32,888
  • 5
  • 17
  • 41
  • @DivyaMani : Can you please share your url if possible.This code should work for each row unless anything changed. – KunduK Dec 27 '19 at 11:54
  • element=rows[rownum].find_element_by_xpath(".//td[contains(@class,'rp-grid-editable-cell rp-grid-editable-cell') and @role='gridcell']") IndexError: list index out of range this is what i'm getting from second iteration.Please help me to fix this – Divya Mani Dec 27 '19 at 13:00
0

Get all rows, then find child td and input:

wait = WebDriverWait(driver, 20)

rows = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "tr[id*='-record-'].x-grid-data-row")))
for row in rows:
    row.find_element_by_css_selector("td[role='gridcell']").click()
    row.find_element_by_name("Quantity").send_keys("10", Keys.ENTER)

Second way with xpath and index:

wait = WebDriverWait(driver, 10)
row_locator = "(//tr[contains(@id,'-record-')])"
rows_len = len(wait.until(EC.presence_of_all_elements_located((By.XPATH, row_locator))))
for i in range(1, rows_len + 1):
    wait.until(EC.element_to_be_clickable((By.XPATH, f"{row_locator}[{i}]/td[@role='gridcell']"))).click()
    driver.find_element_by_xpath(f"{row_locator}[{i}]/input[@name='Quantity']").send_keys("10", Keys.ENTER)
Sers
  • 12,047
  • 2
  • 12
  • 31
  • rows = wait.until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "tr[id*='-record-'].x-grid-data-row"))) File "C:\Users\1024983\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\support\wait.py", line 80, in until raise TimeoutException(message, screen, stacktrace) selenium.common.exceptions.TimeoutException: Message: – Divya Mani Dec 27 '19 at 11:33
  • even after loading this page im getting timeout error. – Divya Mani Dec 27 '19 at 11:34
  • Try it with `presence_of_all_elements_located`. Check updated code – Sers Dec 27 '19 at 11:38
  • row.find_element_by_css_selector("td[role='gridcell']").click() raise exception_class(message, screen, stacktrace) selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable – Divya Mani Dec 27 '19 at 11:59
  • Try second code with xpath with `element_to_be_clickable` or remove click – Sers Dec 27 '19 at 12:15
0

To traverse all the child <input> tags with in the ancestor <tr> tags to send character sequence you need to induce WebDriverWait for the visibility_of_all_elements_located() and you can use the following Locator Strategies:

for element in WebDriverWait(driver, 30).until(EC.visibility_of_all_elements_located((By.XPATH, "//tbody[starts-with(@id, 'gridview') and contains(@id, '-body')]/tr/td//input[@name='Quantity' and starts-with(@id, 'numberfield-')]"))):
    element.send_keys('10')
    element.send_keys(Keys.ENTER)
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352