I have an ascx control which contains dropdownboxes I want to be able to reset with JavaScript.
Because the ascx control is rendered multiple times on the aspx page, I programatically add a distinguishing field to each dropdown such as this in the code behind of the ascx:
var g = Guid.NewGuid().ToString().Replace("-", "");
DropDownListBool.Attributes.Add("jqID", "ddBool" + g);
DropDownListEqual.Attributes.Add("jqID", "ddEq" + g);
On the rendered page, when I want to reset the dropdowns for one of the controls, I have a hyperlink which invokes a javascript function with g as an argument.
In the javascript, using jquery, I try to get both dropdowns for one specific ascx control like this:
function clearControl(g) {
var dds = $("select[jqID = 'dd\\S*" + g + "']");
}
I then do:
jQuery.each(dds, function(i, val) { val.select = 0; });
Should this work? Right now it is resetting seemingly random dropdown boxes.
Is there perhaps a limit to attribute length?
I think you might have better luck with a different selector, say the "ends with" attribute selector.
var dds = $("select[jqID$='" + g + "']");
If you needed to select based on starting with dd and ending with the value of g, you could use a filter and utilize both "ends with" and "starts with";
var dds = $("select[jqID^='dd']").filter( "[jqID$='" + g + '']");
As far as I know you can't use a regular expression when using the attribute equals selector. I'm surprised it works for you at all.
Related
1I have problem that I am going to work with usercontrol in loop. In other word II want to change usercontrols property, but I cant. So I have usercontrol named ucProperty and in it many labels. I have called all of them differently such as LblNameModel, LblImageName, ... In my form there are many usercontrols - ucProperty1,2,.8 and now I want to change their properties (LblNameModel, LblImageName,..) dynamically and in loop.
I try this:
int i = 1;
foreach (Control contrl in this.Controls)
{
if (contrl.Name == ("ucProperty" + i.ToString()))
{
contrl.LblNameModel = "Model" + i.ToString();
contrl.LblImageName = "image" + i.ToString() + ".jpg";
i++;
}
}
enter image description here LblNameModel isnt accepted
But it doesnt work. My problem is properties as LblNameModel after contrl. isnt accepted to programm.
How I can change the properties in loop
and in my usercontrol ucProperty there is the code:
public string LblNameModel
{
get { return lblNameModel.Text; }
set { lblNameModel.Text = value; }
}
this is next result
You must filter and cast to your user controls
using System.Linq;
...
foreach (var uc in this.Controls.OfType<MyUserControlType>())
{
string number = uc.Name.SubString("ucProperty".Length);
uc.LblNameModel = "Model" + number;
uc.LblImageName = "image" + number + ".jpg";
}
If you simply loop through the controls, you get a loop variable typed as Control and you are not able to access properties specific to your user control. The OfType<T> extension method (namespace System.Linq) does both, filter and cast.
I assume that all of these user controls are named as ucProperty<number>. Otherwise add the check
if (uc.Name.StartsWith("ucProperty"))
Note that your approach with i has a problem if the user controls do not appear in the right order. I.e. If the foreach yields "ucProperty4" but i is 3 then this control will be skipped.
I have a form that uses Selenium to go to a page and automate tasks for a user. The only part of the page that changes is a CheckBoxList, and I've been trying to extract the labels from it and mirror them to my form's CheckedListBox so users can make the selection there without seeing the page.
So far I have this:
IList<IWebElement> vehicleGroups = Builder.Driver.FindElements(By.ClassName("vehGrp"));
String[] vehicleText = new String[vehicleGroups.Count];
int i = 0;
foreach (IWebElement element in vehicleGroups)
{
vehicleText[i++] = element.Text;
vehicleGroupList.Items.Add(element.Text);
}
Which works as far as getting the correct number of elements and populating the form, but all of the labels in vehicleText are blank (or just a space.)
An example of the HTML for one of the labels is
<label><input type="checkbox" name="searchQuery.vehicleGroups[0].isSelected" value="on" class="vehGrp"> abcd/efgh ijkl mn (opqrst)</label>
Did I miss something or is the " " messing with the label text? The "abcd/efgh ijkl mn (opqrst)" is what I need but it and the potential number of elements can change daily.
vehicleGroups are the <input> elements, not the <label>s that surround them - and these have no text. This is expected behavior.
You need to get the surrounding <label> element, for example using a method like this:
https://stackoverflow.com/a/12194481/7866667
var vehicleGroupInputElements = driver.FindElements(By.ClassName("vehGrp"));
var vehicleGroupNames = vehicleGroupInputElements
.Select(e => e.FindElement(By.XPath("..")))
.Select(e => e.Text)
.ToArray();
I have a form that automates tasks on a page by user input but I'm having trouble interacting with an element on the page. It's a CheckBoxList with dynamic names and number of elements. The HTML looks like this:
<ol id="ratingModification_SupplierContact_content">
<label><input type="checkbox" name="searchQuery.vehicleGroups[0].isSelected" value="on" class="vehGrp"> abcd ef (ghi)</label> <br>
<label><input type="checkbox" name="searchQuery.vehicleGroups[1].isSelected" value="on" class="vehGrp"> jklm no (pqr)</label> <br>
</ol>
Where " abcd ef (ghi)" is the label of the first checkbox.
I already have a button that extracts the labels from the elements and puts them in an array designed with help from users here:
var vehicleGroupInputElements = Builder.Driver.FindElements(By.ClassName("vehGrp"));
var vehicleGroupNames = vehicleGroupInputElements.Select(f => f.FindElement(By.XPath(".."))).Select(f => f.Text).ToArray();
And I populate my form's CheckedListBox with:
vehicleGroupList.Items.AddRange(vehicleGroupNames);
But when I try to send the user selection back to the page I run into issues. I have tried selecting based on index via IndexOf() and the ClassName but can't figure out the syntax to make it work. Failed example:
foreach (int userChecks in vehicleGroupList.CheckedItems)
{
int checkIndex = vehicleGroupList.Items.IndexOf(userChecks);
var checkTarget = Builder.Driver.FindElements(By.ClassName("vehGrp"));
checkTarget.IndexOf(checkIndex).Click();
}
Which won't compile because int checkIndex cant convert to an IWebElement. I have also tried to build a string to address the index with xpath but it can't find the element or throws a no compound names exception. Failed example:
foreach (int userChecks in vehicleGroupList.CheckedItems)
{
int checkIndex = vehicleGroupList.Items.IndexOf(userChecks);
string elementTarget = "searchQuery.vehicleGroups[" + checkIndex + "].isSelected";
var checkTarget = Builder.Driver.FindElements(By.XPath(string.Format("//option[contains(text(), {0}]", elementTarget))).Click();
}
I've also tried to find the element by label via xpath similar to the above but it never finds it. What is the correct way to find the elements and check them?
When you want to click on each checkbox you can use :
var vehicleGroupInputElements = Builder.Driver.FindElements(By.ClassName("vehGrp"));
foreach (IWebElement checkbox in vehicleGroupInputElements)
{
checkbox.Click();
}
Just looked into Xpath syntax and found the answer. With the help of Chrome's 'copy Xpath' function in inspect mode, I found the path needed and successfully clicked the input element.
Example Xpath of the first input is as follows (notice the HTML for label[index] is 1 more than the way C# would count.)
//*[#id="ratingModification_SupplierContact_content"]/label[1]/input
And solution as follows
//Retrieves the checked items from the form and sends them to the page.
foreach (object checkedItem in vehicleGroupList.CheckedItems)
{
//Gets the index of the checked items.
int checkedIndex = vehicleGroupList.Items.IndexOf(checkedItem);
//Adds 1 to the index to match format of the page HTML.
checkedIndex++;
//Puts the index+1 into a string.
string indexText = checkedIndex.ToString();
//Finds the element by index+1.
var clickTarget = Builder.Driver.FindElement(By.XPath(string.Format("//*[#id='ratingModification_SupplierContact_content']/label[" +indexText+ "]/input")));
clickTarget.Click();
I have a TableCell "cell", where "cell.Text" contains something like
"<input type=\"checkbox\" tabindex=\"-1\" style=\"height:17px\" checked=\"checked\" />".
Goal is to remove the style property "height"!
Plse. note that the "style" attribute can contain some other properties (like "backgroundColor", etc.)
and that whitspaces can be used between "height:" and the value (here "17px")
and that it can (but must not) be terminated with a ";"
etc ...
So it makes no sense to me to parse it (using ".Substring(...)" etc.).
Another possible way would be to create a WebControl and to use ".Remove(...)".
Nice idea, but not working:
var control = Page.ParseControl(cell.Text);
var tmpPage = new Page();
tmpPage.Controls.Add(control);
var webControl = tmpPage.Controls[0] as WebControl; // this return null because "Control" could not be casted to WebControl
var before = webControl.Style;
webControl.Style.Remove(HtmlTextWriterStyle.Height);
var after = webControl.Style;
But this doesnt work. See my comment.
How to reach my goal?
Thx in advance.
I am stuck on this issue and cannot seem to find a way around it.
I have a CheckBoxList control. If you did not know, the FindControl() method on the CheckBoxList control returns "this". Microsoft did it because internally they dont create many ListItem objects but just one.
Anyway, I am trying to find out if a posted back control is one of the controls in my CheckBoxList. My code looks something along the lines of:
if (!(System.Web.UI.ScriptManager.GetCurrent(Page) == null)) {
string postbackControlId = System.Web.UI.ScriptManager.GetCurrent(Page).AsyncPostBackSourceElementID;
if (!string.IsNullOrEmpty(postbackControlId))
{
Control control = ControlFinder.RecursiveFindChildControl(Controls, postbackControlId);
if (!(control == null))
{ }
}
}
Is there anyway to enumerate the child controls of a CheckBoxList or find if an ID that I have is equal to one of theirs?
Thanks,
Mike
The UniqueID of a CheckBox within a CheckBoxList is the UniqueID of the CheckBoxList plus a $ plus the index of the item, so you can check whether postbackControlId is one of the CheckBox controls like this:
if (postbackControlId.StartsWith(this.checkBoxList.UniqueID + "$"))
{
int itemIndex = Convert.ToInt32(
postbackControlId.Substring(this.checkBoxList.UniqueID.Length + 1), 10);
// ...
}
If you're only looking to find out whether the postback was caused by one of the items in the CheckBoxList, you don't need to traverse the entire control hierarchy. You don't even need to drill down into the list. Something like this should work fine:
string elementID = ScriptManager.GetCurrent(Page).AsyncPostBackSourceElementID;
if (elementID.Contains(chkList.UniqueID))
{
//one of the checkboxes caused the postback
}