How to SendKeys to input element that is created ad hoc when clicking in div element parent?
How to SendKeys to input element that is created ad hoc when clicking in div element parent?
I am stuck in this problem: our webpage has a dynamic table that will load values (students' marks) on a div
element. If we click on said div
, a new child element input
will be appended to the div
and we should be able to input a new mark using SendKeys
method. However, when I try to SendKeys, a StaleElementReferenceException
appears.
div
div
input
div
SendKeys
StaleElementReferenceException
Here is the element when the input
is added (had to use a breakpoint as the element disappears as soon as the div
element loses focus):
input
div
<tr>
<td class="indice">1</td>
<td id="accion-1-alumno-0" data-tooltip="" title="Bustos, Guido" class="has-tip titulo">Bustos, Guido</td>
<td data-tooltip="" title="1º ESA" class="has-tip titulo">1º ESA</td>
<td class="nota relative media noeditable k-nivel2_tabla" style="text-align:center; color: #ed1c24!important">
<div id="accion-1-celda-0-0-0" class="elemento comentarios">2,00</div>
</td>
<td class="nota relative " style="text-align:center; color: #ed1c24!important">
<div id="accion-1-celda-1-0-0" class="elemento comentarios">
<input id="editor" type="text" value="2" maxlength="7">
</div>
</td>
<td class="nota relative " style="text-align:center; color: #000000!important">
<div class="elemento comentarios">
<span id="accion-1-editar-2-0" class="block left ellipsis span comentario" title=""></span>
<span id="accion-1-prismaticos-2-0" class="glyphicons glyph_observaciones observacion right"></span>
</div>
</td>
</tr>
And here is the code that I use to click on the div
and try to SendKeys
:
div
SendKeys
IWebElement inputNota = SeleniumHelper.FindByXPath("//td[text() = '"+ nombreAlumno +"']/following-sibling::td/div[contains(@id, 'accion-1-celda')]");
SeleniumHelper.Click(inputNota);
SeleniumHelper.SendKeys(inputNota.FindElement(By.Id("editor")), nota);
Thanks for your time
2 Answers
2
If a new element is appended to the html it means the DOM was refreshed, or at least the <div>
, so the driver
"lost" the previously located elements. You need to relocate it
<div>
driver
string locator = "//td[text() = '"+ nombreAlumno +"']/following-sibling::td/div[contains(@id, 'accion-1-celda')]";
IWebElement inputNota = SeleniumHelper.FindByXPath(locator);
SeleniumHelper.Click(inputNota);
SeleniumHelper.SendKeys(SeleniumHelper.FindByXPath(locator).FindElement(By.Id("editor")), nota);
You would have to wait until the element is no longer stale. A good way to do this is to wait until you can call an attribute on the element such as "Displayed"(Since you are unable to call Displayed if the element is Stale). Below is an example of how I did this using surrounding a try and catch with a webdriver wait, to wait until the element isn't stale... (i.e. wait until I can call an attribute on the element, in this case Displayed)
public static void WaitForVisible(this IWebElement element, IWebDriver driver)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
wait.Until(drv =>
{
try
{
if (element.Displayed)
{
return true;
}
return false;
}
catch
{
return false;
}
});
}
@Rajagopalan I don't think you read my answer correctly... i said that if an element is stale you will be thrown an exception when you attempt to call any of its attributes. This method I have created here means you are waiting until you can call an attribute and thus the element will not be stale. It's what I used to get around Angular removing elements from the DOM. In future don't be childish and threaten to downvote but maybe construct a logical reason as to why its irrelevant
– Taran
2 mins ago
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Oh so when an element becomes visible , element came out from stale? You haven't even understood the meaning of stale element. You will recieve downvote soon.
– Rajagopalan
7 mins ago