3

I'm trying to click on this calendar and insert a date automatically using selenium, but I got the error below:

invalid element state: Element must be user-editable in order to clear it.

HTML snippet

<a id="enddate-dropdown" class="dropdown-toggle" role="button" data-toggle="dropdown" data-target="">
                <p class="custom-datepickers__date-prefix ng-binding">To:</p>
                <!-- ngIf: displayEndDate -->
                <!-- ngIf: !displayEndDate --><div ng-if="!displayEndDate" class="custom-datepickers__no-date ng-scope"></div><!-- end ngIf: !displayEndDate -->
</a>

Code snippet

myclass.SetDateByXpath("//*[@id=\"enddate-dropdown\"]/p", myclass.GetDate("yyyy/MM/dd", mydate));

public void SetDateByXpath(String element, String value)
    {
        WebElement webElement = ExplicitWaitOnElement(By.xpath(element));       
        ((JavascriptExecutor) driver).executeScript(
                "arguments[0].removeAttribute('readonly','readonly')",webElement);
        webElement.clear();
        webElement.sendKeys(value);
    }

If I set the date manually, this is the HTML:

<a id="enddate-dropdown" class="dropdown-toggle" role="button" data-toggle="dropdown" data-target="">
                <p class="custom-datepickers__date-prefix ng-binding">To:</p>
                <!-- ngIf: displayEndDate --><p ng-if="displayEndDate" class="ng-binding ng-scope">2019/11/21</p><!-- end ngIf: displayEndDate -->
                <!-- ngIf: !displayEndDate -->
</a>

Probably the website changed, but now I don't know how can I set this value. Any help will be appreciated.

Thanks

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
Pankwood
  • 1,799
  • 5
  • 24
  • 43

2 Answers2

5

I'm guessing your error is being thrown at the lines:

webElement.clear();
webElement.sendKeys(value)

We can try to work around that by setting values through Javascript instead:

// updated selector for webElement to grab the p element which contains the date string
WebElement webElement = driver.findElement(By.xpath("//*[@id=\"enddate-dropdown\"]/p[@ng-if='displayEndDate']"));

// try setting inner HTML which is the text inside the p
((JavascriptExecutor) driver).executeScript("arguments[0].innerHtml = '" + value + "';", webElement)

// alternative option is to try setting value instead
// ((JavascriptExecutor) driver).executeScript("arguments[0].value = '" + value + "';", webElement)
CEH
  • 5,701
  • 2
  • 16
  • 40
  • Thanks @Christine, you are right, those lines are responsible for trigger the error. I've replaced the code using your Javascript, but I didn't have success setting the date in that field. – Pankwood Nov 15 '19 at 17:38
  • I noticed your XPath `//*[@id=\"enddate-dropdown\"]/div/input` is searching for an `input` element, but I don't see that element in the HTML snippet you provided. Could you include that too, so I can get a full idea of what this date picker looks like? – CEH Nov 15 '19 at 17:39
  • Ohh, it was a typo, the correct XPath is `"//*[@id=\"startdate-dropdown\"]/p"`. I'm gonna edit the post. But still stuck – Pankwood Nov 15 '19 at 17:49
  • Also, I edit the post putting the HTML after I set the date manually. Maybe it can help. – Pankwood Nov 15 '19 at 17:53
  • What happens if you run `.click()` on `//a[@id='enddate-dropdown']`? Is there a calendar popup to let you pick values? I also updated my answer to set `innerHtml` instead of `value` on the element -- it's worth trying that out too. – CEH Nov 15 '19 at 17:57
  • Yes, it is a calendar. I changed my code but still stuck...this is how the HTML looks after running your code: ```

    To:

    ```
    – Pankwood Nov 15 '19 at 18:05
  • I did just realize something -- `//*[@id=\"enddate-dropdown\"]/p` is probably returning the first `p` element under your `a` element, which is not the correct `p` that is getting set with the date. I've updated my answer to try a different selector. – CEH Nov 15 '19 at 18:30
  • Got this error now: `Expected condition failed: waiting for visibility of element located by By.xpath: //*[@id="enddate-dropdown"]/p[@ng-if='displayEndDate']` But yeah, the xpath looks wrong, missing the other p tag and ng-if. – Pankwood Nov 15 '19 at 18:42
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/202432/discussion-between-pankwood-and-christine). – Pankwood Nov 15 '19 at 18:50
2

This error message...

invalid element state: Element must be user-editable in order to clear it.

...implies that the element identified was not in a user-editable state to invoke clear() method.


To insert a date with in a dropdown-toggle with an Angular element there are two approaches:

  • Either you can click() on the calendar and insert a date using sendKeys()
  • Or you can use executeScript() to invoke removeAttribute() the readonly attribute.

However, as per the HTML you have shared it seems the element which gets populated with the date string i.e. 2019/11/21 is not readily available within the HTML DOM. So we can infer that the following element gets added to the DOM Tree as a result of interaction with other WebElements which is as follows:

<p ng-if="displayEndDate" class="ng-binding ng-scope">2019/11/21</p>

Hence the best approach would be,

  • First to invoke click() on the element readily available within the HTML inducing WebDriverWait.
  • Next to invoke sendKeys() on the newly created element WebDriverWait.
  • Code Block:

    //element -> myclass.SetDateByXpath("//a[@class='dropdown-toggle' and @id='enddate-dropdown']"
    // observe the change in the ^^^ xpath ^^^
    //value -> myclass.GetDate("yyyy/MM/dd", mydate));
    
    public void SetDateByXpath(String element, String value)
    {
        WebElement webElement = ExplicitWaitOnElement(By.xpath(element));       
        webElement.click();
        WebElement webElement_new = ExplicitWaitOnElement(By.xpath("//a[@class='dropdown-toggle' and @id='enddate-dropdown']//p[@class='ng-binding ng-scope' and @ng-if='displayEndDate']"));
        webElement_new.clear();
        webElement_new.sendKeys(value);
    }
    

Reference

You can find a relevant discussion in:

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352