I cannot access the text of a Web Element - c#

I have bunch of radio buttons, and would like to get the text from the labels for each of them. This is what I have tried so far:
IList<IWebElement> radioButtons = wd.FindElements(By.Name("Components[0].Entity.ComponentSubTypeId"));
foreach (IWebElement i in radioButtons)
{
Console.WriteLine(i.Text);
}
I know that they are getting stored in the List, because when I remove the .Text from above, a number of OpenQA.Selenium.Firefox.FirefoxWebElement's are written to the Output console, with it matching exactly to the number of radio buttons located on the page.
Here is the HTML of one of the radio buttons on the page:
<li class="optionListItem">
<span class="floatLeftSmallMargin componentTypeOptions">
<input class="required" id="Components_0__Entity_Entity_ComponentTypeId_PublicationGravure" name="Components[0].Entity.ComponentSubTypeId" type="radio" value="-2147380659" />
</span>
<span class="optionListItemText componentTypeOptions">
<label for="Components_0__Entity_Entity_ComponentTypeId_PublicationGravure">Publication Gravure</label>
<span class="helpButton" data-title="Publication Gravure" data-text="A printing method on a substrate that is subsequently formed into books, magazines, catalogues, brochures, directories, newspaper supplements or other types of printed materials.">
</span>
</span>
<div class="clear"></div>
</li>
But again, when I append the .Text to the index i in the foreach parameter, there is nothing being written to the output console.

The problem is your IList<IWebElement> radioButtons does not contain the label.
It only contains the input which does not have any text. So when you do .Text you will not see any text.
IList<IWebElement> labels = wd.FindElements(By.CssSelector(".optionListItem .optionListItemText label"));
Now Iterate on labels and call .Text, you will see the label names.

The reason why it's returning nothing is because the radio buttons indeed don't have text but you selected them, here is a pratical example of how .Text works:
<li >
<span id="foo">My text</span>
<input name="bar" type="radio"/>I'm not part of the radio
</li>
Now let's extract the text from above
//This will return "My text"
IWebElement spanText= wd.FindElement(By.CssSelector("#foo")).Text
//This will return empty
IWebElement spanText= wd.FindElement(By.XpathSelector("//input")).Text
In your case it should look something like this
IList<IWebElement> labels = wd.FindElements(By.CssSelector(".optionListItem .optionListItemText label"));
foreach (IWebElement i in labels)
{
Console.WriteLine(i.Text);
}

Related

Hide <li> element if a scope value is null

I want to hide certain items in my list depending on whether a scope value is null.
This is my controller:
angular.module("umbraco").controller("my.custom.grideditorcontroller", function ($scope) {
$scope.control.heading;
$scope.control.punkt1 = null;
$scope.control.punkt2 = null;
$scope.control.punkt3 = null;
$scope.control.punkt4 = null;
$scope.control.punkt5 = null;
});
I have 5 li elements as well, that I want to show/hide depending on whether each of these scope properties has
This is one of my li elements:
<li ng-hide="control.punkt5 == null">#Model.punkt5</li>
This doesn't work, as the element is still being shown.
My properties use 2-way binding with my input elements:
<input type="text" ng-model="control.punkt1" placeholder="Indtast første punkt...">
But the input and the li elements are located in 2 separate HTML documents, since I am creating a grid editor for Umbraco.
This is my folder structure: https://i.imgur.com/ZbejcOl.png
Where the infobox.cshtml file contains the li elements, and the infobox.html file contains the input elements.
I tried using razoe code in my ng-hide/show condition, but that didn't return any boolean values. What is the correct way to approach this without using razor?
My render view (infobox.cshtml) receives a dynamic model of type JObject, but I can't use any of its methods in my ng-hide condition as it is c#. I've tried everything as mentioned in my previous post.
Edit:
<div ng-controller="my.custom.grideditorcontroller">
<div class="list-group">
<div class="list-group-item">
<h4 class="list-group-item-heading">#Model.heading</h4>
<ul class="ul-with-bullets">
<li ng-show="IsProperty(#Model,'punkt1')">#Model.punkt1</li>
<li ng-show="#Model.GetType().GetProperty("punkt2") != null">#Model.punkt2</li>
<li ng-show="#Model.GetType().GetProperty("punkt3") != null">#Model.punkt3</li>
<li ng-show="#Model.GetType().GetProperty("punkt4") != null">#Model.punkt4</li>
<li ng-hide="control.punkt5">#Model.punkt5</li>
</ul>
</div>
</div>
</div>
use this code
$scope.control={
punkt1:null,
punkt2:null,
punkt3:null,
punkt4:null,
punkt5:null
};
and now in your view you can check your control properties

Additional html tags with dynamic radio button

I am creating some radio buttons dynamically by:
Regions.ascx
<ul class="form_items" ID="radioList" runat="server" clientidmode="Static">
</ul>
In Regions.ascx.cs
foreach (var region in Config.ConfigString("str_Regions").Split(','))
{
HtmlGenericControl li = new HtmlGenericControl("li");
RadioButton regionRadio = new RadioButton();
regionRadio.Text = region;
regionRadio.ID = "Radio"+(i++).ToString();
regionRadio.Attributes.Add("name", "region");
regionRadio.Attributes.Add("value", region);
regionRadio.TextAlign = TextAlign.Right;
li.Controls.Add(regionRadio);
radioList.Controls.Add(li);
}
A lot of extra HTML tags are appearing which I don't want. I am getting output as:
<ul id="radioList" class="form_items">
<li>
<span name="region"><input id="MainContent_contactUs_Radio1" type="radio" name="ctl00$MainContent$contactUs$Radio1" value="Australia">
<label for="MainContent_contactUs_Radio1">Australia</label>
</span>
</li>
<li>
<span name="region"><input id="MainContent_contactUs_Radio2" type="radio" name="ctl00$MainContent$contactUs$Radio2" value="America">
<label for="MainContent_contactUs_Radio2">America</label>
</span>
</li>
</ul>
The label under which the 'Australia/America' is coming causes the wrong look by inheriting the styles aligned to all labels.
While I just want
<ul id="radioList" class="form_items">
<li><input id="MainContent_contactUs_Radio1" type="radio" name="ctl00$MainContent$contactUs$Radio1" value="Australia">"Australia"</li><li><input id="MainContent_contactUs_Radio2" type="radio" name="ctl00$MainContent$contactUs$Radio2" value="America">"America"</li></ul>
If you are using System.Web.UI.Webcontrols it will render your control with span. You can see why its rendering between span.
Why does ASP.Net RadioButton and CheckBox render inside a Span?
There two ways to overcome this. First you need to add attribute to input controls not span right now when you directly add attribute it will do that way.
See my blog post about it- http://www.dotnetjalps.com/2014/04/aspnet-checkbox-button-attributes-javascript.html
You need to add attribute like below.
myCheckBox.InputAttributes.Add("onblur", "onBlur();");
For text align and other stuff I suggest you use System.Web.UI.HtmlControls where you can use HtmlInputRadioButton instead of System.Web.UI.Webcontrols radio button. Here you can also manage all HTML attribute very easily.
Another thing you can do like adding labels and HTMLInputRadioButton separately and add class to your label as per your requirement.
string[] regions = {"Autralia", "Asia", "US"};
foreach (var region in regions)
{
HtmlGenericControl li = new HtmlGenericControl("li");
HtmlInputRadioButton radioButton=new HtmlInputRadioButton
{Value = region,
Name = region};
li.Controls.Add(radioButton);
Label label=new Label {Text = region, CssClass = "YourCSSClass"};
li.Controls.Add(label);
radioList.Controls.Add(li);
}
Hopefully this have more controls on css style
I think text-align set the horizontal position of your radio button in its container.
so, check if your container does or not wrap to your radio button.

Parsing Radio button name only bringing up one value

I have written some code to parse the name from some radio buttons.
<div id="First" class="Size-Inputs">
<input rel="8" type="radio" value="13051374" name="idProduct-13051359"/> <span rel="L">L</span>
<input rel="8" type="radio" value="13051373" name="idProduct-13051359"/> <span rel="M">M</span>
<input rel="8" type="radio" value="13051372" name="idProduct-13051359"/> <span rel="S">S</span>
<input rel="8" type="radio" value="13051375"name="idProduct-13051359"/> <span rel="XL">XL</span> </div>
The problem which I am having when I try to parse the span rel to get the size names eg L,M,S,XL it is only coming up with the value L four times.
The code I am using is;
HtmlNodeCollection link = doc.DocumentNode.SelectNodes("//*[#id='First']/input");
if (link != null)
{
foreach (HtmlNode item in link)
{
string name = item.SelectSingleNode("//*[#id='First']/span").InnerText;
Console.WriteLine(name);
}
Console.ReadLine();
}
I was just wondering why the it is only picking up one value and printing it four times and how can you make it pick up the span rel for each of the variant input. Thanks for any help which you can provide
It seems that you don't need <input> element but <span> element. And <span> is not child of <input>. So assuming that it isn't typo or paste error, you can select <span> directly without selecting <input> element first :
HtmlNodeCollection link = doc.DocumentNode.SelectNodes("//*[#id='First']/span");
if (link != null)
{
foreach (HtmlNode item in link)
{
string name = item.InnerText;
Console.WriteLine(name);
}
Console.ReadLine();
}

Extract text from a div

I am trying to make a DropDownList using divs and jquery (so that I can style it as I want)...and its working but the problem is I cant get the selected value from the list..
After selection of the option I am copying the selected value into the a div.. and I want to extract this using c# (in .aspx.cs page)... I've tried to do it using string builder and innerHtml(after adding runat="server" to the div).. but it doesn't work ...code is as follows
.aspx Page:
<div class="ddl">
<div id="lowertriangle" class="lowertriangle"></div>
<div id="uppertriangle" class="uppertriangle"></div>
<div id="label" class="labeldiv_dd" runat="server"></div>//***This is the div from which I want to extract value***
<div id="options" class="optionsidv_dd">
<ul id="options_ul">
<li id="0">Select One Option</li>
<li id="1">Option 1</li>
<li id="2">Option 2</li>
<li id="3">Option 3</li>
<li id="4">Option 4</li>
<li id="5">Option 5</li>
</ul>
</div>
</div>
aspx.cs page
Method 1 that I tried:
string sel_text = label.InnerHtml;
display_sel_value.Text = sel_text.ToString();
2nd method:
var sb = new StringBuilder();
label.RenderControl(new HtmlTextWriter(new StringWriter(sb)));
string s = sb.ToString();
Kindly point out my mistakes and help me in this regard(in extracting innerHTML of the div that is).
Thanks
No, putting content in a div won't work.
Your example isn't complete enough to see all that happens, but let's assume that you're in a standard <form>, you're setting the div's inner HTML to a value with Javascript and then you're submitting in the standard way.
Then one way to do what you want is to use a hidden input and setting its value attribute instead of its contents.
<input id="label" class="labeldiv_dd" runat="server" type="hidden">
In the codebehind, the C# can retrieve the value from this control after submitting with the .Value property.
Ok guys thx for your replies..I found a way around the problem...I used HiddenField control to store the selected value using jQuery like so
$("#options_ul li").click(function () {
var text = this.innerHTML;
***$('#<%= selectedvalue.ClientID %>').val(text);***
$("#options_ul li").css("background-color", "#c2c2c2");
$(this).css("background-color", "white");
//var prev = this.id;
//document.getElementById("label").innerHTML = text;
toggleHeight();
});
and then accessed it server side using
selectedvalue.value;
PS: "selectedvalue" is id of the hiddenfield control

Dynamic load of html code

In my Asp.net website I have a repeater which loads dynamically from code-behind. In code outside the repeater I have an "add" button. On click, I want to add the same controls from repeater asynchronously. On click of the "add" button function NewRow() is called:
function NewRow(){
var guid = jQuery.guid++;
var panel = $('#MainContent_Panel1');
var textboxText = $('#MainContent_TextBox');
panel.after("<span LabelGroup="+i+">Test Text:</span>
<span TextGroup="+i+">"+textboxText.val()+"<br /></span>
<span LabelGroup="+i+">Test Text : </span>
<input type='text' customID="+guid+"/>
<input type='button' Class='Button' ButtonGroup='"+i+"' value='Button Text' /></br>
");
i++;
}
I hate what I am currently doing, because there is so much hardcoded code. Is there any way I can make it more dynamic?
And is there any way to place my newly added row more precisely in dynamic control like repeater?
You could try a templating engine like mustache.js, or you can do it by hand like this:
In your HTML, include a script tag, with type="text/html". This will tell the rendering engine to do not try to render the contents. Inside this tag, you will write the template code for each column.
I marked each variable section as $variable:
$i
$textboxText
$guid
​<script type="text/html"​​​​​​​​​​​​​​​​ id="template">
<span LabelGroup='$i'>Test Text:</span>
<span TextGroup='$i'>$textboxText<br /></span>
<span LabelGroup='$i'>Test Text : </span>
<input type='text' customID='$guid'/>
<input type='button' Class='Button' ButtonGroup='$i' value='Button Text' /></br>
</script>
<!-- And here, some testing elements -->
​<input type="button" id="New" value="New Row">
<input type="text" id="MainContent_TextBox" value="Some Value">
<div id="MainContent_Panel1"></div>​​​​​​​
And then, in your javascript, you only need to get the html contents of the script tag, then replace each $variable with the value to use.
Please note that you should use /g when calling .replace, to replace all ocurrencies of your $variable in the template.
i = 1;
$("#New").click(NewRow);
function NewRow(){
var guid = jQuery.guid++;
var panel = $('#MainContent_Panel1');
var textboxText = $('#MainContent_TextBox').val();
var html = $("#template").html()
.replace(/\$i/g,i)
.replace(/\$guid/g,guid)
.replace(/\$textboxText/g,textboxText);
panel.append(html);
i++;
​}​
Using this approach, you are separating html from js code. Something that will help you in the future if you have to maintain this.
Hope it helps.
You could create your tags on the fly like this:
var $span1 = $("<span />").text("your text").attr("TextGroup", i);
...
var $text = $('<input type="text" />').attr("customID", guid);
...
var $button = $('<input type="button" />').addClass("Button").val("Button text").attr("ButtonGroup", i);
And then just add them to the control container
$panel.append($span1).append(...);
Try it live on Fiddler

Categories