Change value of a table cell with WatIn - c#

Using WatiN, can I access an url and change the value of a html table cell defined this way :
<TABLE class=table1>
<TBODY>
<TR class=dis>
<TD> rowSpan="1" colSpan="1"
Famille
<INPUT name="familySearch" onkeyup="toMaj(document.forms[0],'familySearch');changeFormEltFocus(3, 'eng.facLab');" onfocus=onKeyBack() maxLength=3 size=3 value="AAA"></input>
<A onclick="popupFamily('RFOS');" tabIndex=-1 href="#"><IMG border=0 hspace=4 alt=" " src="/ppm/images/picto_loupe.gif" align=absMiddle></A>
</TD>
</TR>
</TBODY>
I tried to do it using :
browser.Table(Find.ByClass("table1")).TableRows[0].TableCells[0].SetAttributeValue("AAA", "X82");
But I'm getting an error saying I can't access the cell. Any idea ? Thanks

Can you try focusing and then setting the value.
browser.TextField(Find.ByName("familySearch")).Focus();
browser.TextField(Find.ByName("familySearch")).TypeText("AAA");

Related

How do I select a button before text using Selenium C#

I have a bit of a dilemma. I have a table of 3 columns. Column 1 is a button to make that row active. The 2nd column is the name of the person. And the 3rd column is a button to view the person's details.
Using Selenium C#, I can search for a specific person in the table and click the button to View, using the code below:
currentDriver.FindElement(By.XPath("(.//*[normalize-space(text()) and normalize-space(.)='Name of person'])")).Click();
How do I select the button before the name of the person?
EDIT: Added HTML -
<table class="table table-hover>
<thead>...</thead>
<tbody id="listCompany">
<tr>
<td>
<span id="a5" class="badge btnActivateCompany clsActiveCompany15" ><i class="fas fa-times"></i></span>
</td>
<td>Test Director</td>
<td>
<button.>...</button>
</td>
</tr>
</tbody>
The class btnActivateCompany is used several times depending on how many rows exist. And the id changes depending on the rows as well. So I have to search to find the correct record and then select the span before it.
I tried the following to select the object:
currentDriver.FindElement(By.XPath("(.//*[normalize-space(text()) and normalize-space(.)='Test Director'])[1]/preceding::span[1]")).Click();
I get the feeling you've modified the HTML as you've posted. I guess you stripped out some data and typed other content in. You say you want the button before the person, but in your code the button is after the person?
Either way, both are achievable. I made a few quick additions to help visibility. If i'm wrong please correct me as it influences xpaths.
Quick change log: I ran your html through a beautifier, added text to all the columns for visibility, added "border=1" to the table, remove the . from button, added the </table> and duplicated the row so i can check unique objects are found.
This is the result: (useful if anyone else wants to chip in an identifier)
<html>
<body>
<table class="table table-hover" border=1>
<thead>...</thead>
<tbody id="listCompany">
<tr>
<td>
<span id="a5" class="badge btnActivateCompany clsActiveCompany15" >
<i class="fas fa-times"> Column 1</i>
</span>
</td>
<td>Test Director</td>
<td>
<button> Button in col 3
</button>
</td>
</tr>
<tr>
<td>
<span id="a5" class="badge btnActivateCompany clsActiveCompany15" >
<i class="fas fa-times"> Column 1</i>
</span>
</td>
<td>Second Row!</td>
<td>
<button> Button in col 3
</button>
</td>
</tr>
</tbody>
</table>
</body>
</html>
That renders like this:
Based on fact you say you can get the text in the middle column...
If you want the button in column 3, you can try xpath:
//td[text()='Test Director']/parent::*/td/button
If you want the span in column 1, you can try:
//td[text()='Test Director']/parent::*/td/span[contains(#class,'btnActivateCompany')]
In both of these instances this selects a unique hit in the source.
However, please note, this is dependent on the html provided. If there are other elements/attributes in the table the xpath might need more work. I'm happy to help more but you'll need to share more content.

MVC: Displaying table after button pressed

Hi I have a question is that possible to have function to display my table after the button was pressed, because now it's always on? I've tried with some IF functions but they weren't working.
My code:
#using (Html.BeginForm("Search", "Home", FormMethod.Post))
{
<br />
<span style="font-weight: bold">Tytuł filmu:</span> #Html.TextBox("VideoName")
<input type="submit" value="Szukaj" class="btn-primary" />
<br />
<br />
<table cellpadding="0" cellspacing="0">
<tr>
<th>
#Html.DisplayNameFor(model => model.ImageUrl)
</th>
<th>
#Html.DisplayNameFor(model => model.VideoName)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ImageUrl)
</td>
<td>
#Html.DisplayFor(modelItem => item.VideoName)
</td>
</tr>
}
</table>
}
If you put your markup inside a conditional block as follows:
#if (true)
{
#* PUT MARKUP HERE *#
}
Then the markup will only appear when the if condition is true.
Alternatively, you can use client-side code to simply hide the markup. I don't know which is best, because you haven't provided any details about what you are doing.
Instead of saying THE button, perhaps you should've talked about what kind of button you have and what is it supposed to do. If it works server side, use my first suggestion. If it needs to work client side, use my second suggestion.
You can do that in number of ways,
Javascript:
document.getElementById('mytable').style.display = 'block';
Give your table an ID and set its display to none; initially, then using javascript on the button click switch the table display to block;
function buttonClick(){
document.getElementById('myTable').style.display = 'block';
}
<table id='myTable' style='display:none;'>...</table>
<input type="submit" value="Szukaj" class="btn-primary" onclick='buttonClick()' />
Notes:
- It can be much easier if you are using jquery
- You can use event listener for the button click
Server side code:
On your action method set a TempData or ViewBag variable and then in the html check if this value exist, if true show the table
I am sure there are many other ways to do that but most of them will be around both ideas I listed.
You can have a button that toggles the visibility of the table, call the below function on the button onclick event to show or hide the table.
function toggleTable() {
var lTable = document.getElementById("YourTableId");
lTable.style.display = (lTable.style.display == "table") ? "none" : "table";
}
You have several good answers but it depends on exactly what you are trying to accomplish. I've used a variety of what has been provided. You mention showing table on button click. Do you also need to hide table if said button is clicked again? If so, client side jQuery and .toggle() could help.
$(document).ready(function(){
$("button").click(function(){
$("#myTable").toggle();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button>Toggle</button>
<table id="myTable" style="border: 1px solid black; display: none">
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
<tr>
<td>Data 1</td>
<td>Data 2</td>
</tr>
</table>

Using a C# variable as a table element

What I have is this:
<table>
<tr bgcolor="#007ACC" style="color:White">
<td width="145">Account Group</td>
<td width="80"></td>
<td width="10">Active</td>
</tr>
<tr>
·
·
</tr>
</table>
What I need to do is make it so "Account Group" can be changed based on a user's treeview selection. i.e., if the user selects a Child node, I need to change that to "Account Number".
Is it possible to change a table element on-the-fly like that? If so, how would I do this?
Place a label in <td> to display text, so that you can change them based on label id
<td width="145">
<asp:Label Text="Account Group" ID="lblUserContent" runat="server" />
</td>
As per treeview selection changes you can change the text by using following code:
if(your condition)
lblUserContent.Text="Account Number"
else
lblUserContent.Text="Account Group"
The best way to do this will depend on how you're using your treeview, but here's a quick way to output the value of a C# variable into your table:
<table>
<tr bgcolor="#007ACC" style="color:White">
<td width="145"><%# Eval("MyCSharpVariable") %></td>
<td width="80"></td>
<td width="10">Active</td>
</tr>
<tr>
·
·
</tr>
</table>

Get client side HTML changes on postback

I want to add rows to a table with javascript, but I also want to be able to find out what those rows are on postback. Is there a way to do that?
I also want to be able to populate the original rows in the table from the server (I'm thinking with a repeater). Is it still possible to do that?
That's not much of a description but I think that covers it...
The code currently looks something like this
<table id="myTable">
<tr> <td> some static row </td> </tr>
<asp:repeater id="rptTest" runat="server">
<HeaderTemplate>
<tr class="dgheader">
<th> head1 </th>
<th> head2 </th>
<th></th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr class="<%# (Container.ItemIndex%2 == 0) ? "dgitem" : "dgalternatingitem" %>">
<td><%# Eval("val1") %> </td>
<td><%# Eval("val2") %> </td>
<td><a class="dgdeletebutton" href="javascript:delete(this)"></a></td>
</tr>
</ItemTemplate>
</asp:repeater>
</table>
At the moment all I'm wondering is how, server side, I can get a version of the table that has whatever changes I made client side.
In order to get any information from a client in the manner you describe, you need to include a field in your form submit.
You will probably want hidden(s) field. Any time you add a row, either add a hidden field for each value you want to capture (such as val1 and val2) or have one hidden field, and when you add a row, append the information you want to the existing row.
I would warn against posting straight html, you probably only need the values not the full markup, and you most likely don't want to sanitize the html and parse it for the information you want.
So to get you a head start you can add hidden inputs:
<tr class="<%# (Container.ItemIndex%2 == 0) ? "dgitem" : "dgalternatingitem" %>">
<input type="hidden" name="Row[1].val1" value="myvalue" />
<td><%# Eval("val1") %> </td>
<input type="hidden" name="Row[1].val2" value="myvalue" />
<td><%# Eval("val2") %> </td>
<td><a class="dgdeletebutton" href="javascript:delete(this)"></a></td>
</tr>
You can then get the submitted values on the backend:
HttpContext.Current.Request.Form["Row[1].val1"]
This is from memory, the line above might not be correct.

XPath drops contents of td column on an HTML page for screen scraping

Below you find an excerpt of code used to screen scrape an economic calendar.
The HTML page that it parses using XPath includes this row as the first rown
in a table. (Only pasted this row instead of the entire HTML page.)
<tr class="calendar_row newday singleevent" data-eventid="42064"> <td class="date"><div class="date">Sun<div>Dec 23</div></div></td> <td class="time">All Day</td> <td class="currency">JPY</td> <td class="impact"> <div title="Non-Economic" class="holiday"></div> </td> <td class="event"><div>Bank Holiday</div></td> <td class="detail"><a class="calendar_detail level1" data-level="1"></a></td> <td class="actual"> </td> <td class="forecast"></td> <td class="previous"></td> <td class="graph"></td> </tr>
This code that selects the first tr row using XPath:
var doc = new HtmlDocument();
doc.Load(new StringReader(html));
var rows = doc.DocumentNode.SelectNodes("//tr[#class=\"calendar_row\"]");
var rowHtml = rows[0].InnerHtml;
The problem is that rowHtml returns this:
<td class="date"></td> <td class="time">All Day</td> <td class="currency">EUR</td> <td class="impact"> <div title="Non-Economic" class="holiday"></div> </td> <td class="event"> <div>French Bank Holiday</div> </td> <td class="detail"><a class="calendar_detail level2" data-level="2"></a></td> <td class="actual"> </td> <td class="forecast"></td> <td class="previous"></td> <td class="graph"></td>
Now you can see that the contents of the td column for the date vanished! Why?
I've experimented many things and stumped as to why it drops the contents of that column.
The other columns have content that it keeps. So what's wrong with the date column?
Is there some kind of setting or property somewhere to cause or prevent dropping contents?
Even if you haven't got a clue what's wrong but have some suggestions of a way to investigate it more.
Like #AlexeiLevenkov mentioned, you must be selecting a different row than what you want. You've pruned too much of essential problem away in an effort to simplify, but it's still clear what's wrong...
Consider that your input document might basically look like this:
<?xml version="1.0" encoding="UTF-8"?>
<table>
<tr class="calendar_row" data-eventid="12345">
<td>This IS NOT the tr you're looking for</td>
</tr>
<tr class="calendar_row newday singleevent" data-eventid="42064">
<td>This IS the tr you're looking for</td>
</tr>
</table>
The test #class="calendar_row" won't match against the tr you show, but it will match against the first row.
You could change your test to be contains(#class,'calendar_row') instead, but that would match both rows. You're going to have to identify some content or attribute that's unique to the row you desire. Perhaps the #data-eventid attribute would work -- can't tell without seeing your whole input file.

Categories

Resources