Home > Software engineering >  Element is clickable but not interactable (HTML, Selenium, Python)
Element is clickable but not interactable (HTML, Selenium, Python)

Time:08-31

So I'm trying to send keys to an element using Selenium. I'm thrown with:

ElementNotInteractableException: Message: element not interactable

The thing that's confusing me is that I can click the element without any problem. (I can see that happen on the browser)

I've tried implicitly wait but that doesn't work. The said element is well within the screen so that's not a problem either.

Here is the HTML for the said element

<td  id="c30"><input autocomplete="off"  id="f30" name="sd3ubq41" readonly="" size="2" value="3"/></td>

Here is my code:

my_element2 = driver.find_elements(By.ID, "c30")
my_element2[0].click()
driver.implicitly_wait(20)
my_element2[0].send_keys(4)
my_element2[0].submit()
print(my_element2)

In case you want to see what the element looks like when I print it:

[<selenium.webdriver.remote.webelement.WebElement (session="5eb8e8b3fc146dc6a2ba970b992afe1c", element="7b340688-ce12-4c6f-9066-e6c54db6ebf4")>]

CodePudding user response:

Given the HTML:

<td  id="c30">
    <input autocomplete="off"  id="f30" name="sd3ubq41" readonly="" size="2" value="3"/>
</td>

The element is having the readonly attribute. So you can't click on the element in this state.

Presumably, you have to take some other actions so the readonly attribute is removed from the element and then you can invoke the click.

CodePudding user response:

There are a few issues...

  1. You've used the wrong ID. The ID you are using is for the TD and not the INPUT. The ID for the INPUT is "f30", not "c30".

  2. As you stated, you can click the element but you get an error when you use .send_keys(). The reason for this is because you can't interact with the TD using .send_keys(). You need to change the locator to find the INPUT.

  3. ... even after all that, you still won't be able to .send_keys() to the INPUT because it's marked as readonly. You can't change the value of the INPUT in that state so .send_keys() throws an exception. You can click on it, get the value, but not set a new value. Since you haven't provided a link the page, I don't know if that particular element can be toggled to be editable through other means.


Looking at your code, I wanted to offer a few suggestions.

  1. Since you only ever use the first element, my_element2[0], in your code, there's no reason to use .find_elements() (plural). Use .find_element() (singular) instead and it just returns the first element, e.g.

    driver.find_element(By.ID, "f30").send_keys(4)
    
  2. There's no need to click the element before using .send_keys().

  3. implicitly_wait() doesn't wait when you call it, it's a one-time setting of a timeout that lasts the life of the driver. Set it once at the start of the script and you never need to set it again. Having said that, using implicitly_wait() is not a good practice. Simon Stewart, the creator of WebDriver, and other contributors have warned against using implicitly_wait(). You should instead use WebDriverWait when a wait is needed.

  4. Using .submit() on an INPUT that is a text field doesn't generally do anything (unless it's in a FORM).

  5. Using print() on an element, or in this case an element collection, isn't going to print anything useful. It prints the session and element GUIDs which isn't likely what you were expecting. Since this is an INPUT, you want to use

    print(my_element2.get_attribute('value'))
    

    For other elements you would use,

    print(element.text)
    

    to print the text contained in the element.

Hopefully that helps.

Updating your code with my suggestions would look like

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "f30"))
# element.send_keys(4) # doesn't work when readonly
print(element.get_attribute('value')) # print whatever the current value of the INPUT is
  • Related