Click Checkbox by Value Selenium - c#

I have google around a bit trying to finds some way you can click check boxes by entering a value, similar what you can use to select values in Drop Down List.
But havent found a way yet.
I have two check boxes with Yes and No
div class="radio">
<label>
<input type="radio" name="LongTermContract" value="Yes" autocomplete="off" checked="">Yes
</label>
<label>
<input type="radio" name="LongTermContract" value="No" autocomplete="off">No </label>
</div>
I'm also using PageObjects,
[FindsBy(How = How.Name, Using = "LongTermContract")]
public IWebElement radioBtnLongTermContract { get; set; }
This is the Method I have.
public static void SelectOptions(this IWebElement element, string value)
{
PropertiesCollection.driver.FindElement(By.XPath("//input[#value='" + value + "']")).Click();
}
Now if im trying this
public void SelectValue(){
Reporting("NO");
}
I get an error that it does not find the element
Additional information: no such element: Unable to locate element:
{"method":"xpath","selector":"//input[#value='NO']"}
Any ideas tips?

This is the code snippet is in java. You need to pass value either Yes or No it will select respective radio button as the same value used for <input> tag's attribute value
public static void SelectOptions(String value)
{
driver.findElement(By.xpath("//input[#value='"+value+"']")).click();
}

Related

Dynamically change the Body for a component in Blazor

I'm trying to achive a search functionality for Blazor-server where the idea is to use it anytime on the site by typing on a search box which causes the page to change the #Body for a component that shows the results of the search.
Currently I'm able to do the search well on the MainLayout but this is by having already a list there and the Body component either below or on top. What I need is to only show the List AFTER I input something on the search bar and to replace it with the Body.
Here is what works but whithout the issue I am having.
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" #oninput="(ChangeEventArgs e)=>SearchHandler(e)" />
<BrowseListShared #ref="BrowseListShared" />
#Body
code{
public string Searched { get; set; }
protected BrowseListShared BrowseListShared;
public void SearchHandler(ChangeEventArgs e)
{
Searched = e.Value.ToString();
BrowseListShared.UpdadeMe(Searched);
}
}
And this is my attempt at trying to make the replacement which gives me the error "Object reference not set to an instance of an object.", the Error shows when I type something in the search box.
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" #oninput="(ChangeEventArgs e)=>SearchHandler(e)" />
#if (setVisible){
<BrowseListShared #ref="BrowseListShared" />
}else{
#Body
}
code{
public string Searched { get; set; }
protected BrowseListShared BrowseListShared;
private bool setVisible=false;
public void SearchHandler(ChangeEventArgs e)
{
if (e != null && e.Value.ToString() != ""){
setVisible = true;
}else{
setVisible=false;
}
Searched = e.Value.ToString();
BrowseListShared.UpdadeMe(Searched);
}
}
Hope someone can give me some direction to deal with this, thank you.
Edit:
Adding if(BrowseLit != null) to avoid error does make it work with some issues.
1- the first character makes so it shows just the list without the search because on the first character the code doesnt have the reference yet for the BrowseListShared so it skips the BrowseListShared.UpdateMe for the first tipe.
2- On deleting the text in the box completely until its blank and typing again will cause this error 'Cannot access a disposed object.'
There shouldn't be an issue to add a small if-block, the following is a basic concept that works for me:
<button #onclick="#( () => test = !test )">test</button>
#if (!test)
{
#Body
}
else
{
<span>some other search content - use a component here
and pass the data as a parameter to it, and its OnParametersSetAsync
can fetch needed data: #test</span>
}
#code{
bool test { get; set; }
}
I would also suggest you try using parameters for the search details instead of a reference.
If you want to show a particular page with search results, you can consider navigating the user to that page (e.g., pass the search query as a route parameter to it) - then it will render only what you want in the #Body - which can range from nothing, to search results, to a lot of other things.

Two way data/event binding w/ non strings (Blazor)

Is it possible to two way bind or bind to an event in Blazor w/ non strings? I have done this with text without an issue but any other type of object is causing me issues.
For example, I have a method that executes when inputting text in a box which is based on the value inputted as well as several other inputs on the form.
<InputNumber step=".01" class="form-control form-control-xs" #bind-Value="#Salary" #bind-Value:event="onkeydown"/>
private decimal salary {get; set;}
public decimal Salary
{
get
{
return salary;
}
set
{
salary = value;
CalculationHere();
}
}
When I do this, I get the below error:
I have also tried passing it in as a parameter like so:
#oninput="#((ChangeEventArgs __e) => CalculationHere(Convert.ToDecimal(__e.Value)"
This also does not work as it causes an error when the textbox is empty and doesn't fire for all inputs (have tried on keydown as well). There are also a lot of parameters so if possible I'd like to avoid this.
I should also note that when I run this project, set a breakpoint in the method being called, and bind like the below, it DOES work. However, removing the breakpoint stops it from working. This has left me VERY confused.
<InputNumber step=".01" class="form-control form-control-xs" #bind-Value="#Salary" #oninput="(() => CalculationHere())"/>
Is there a best practice regarding this? I'm new to web development and Blazor itself is very new so I'm not sure what the best route to go here is... Any advice? Thanks!
When you tell Blazor that it should update the value of a variable via events such as onkeydown, it does not know what to do with the event args provided to it. To achieve a two-way binding in such a case, you need to do the binding manually.
Add an #oninput directive to your InputNumber Component with the value "#((e) => #employee.Salary = Convert.ToDecimal(e.Value))"
Your InputNumber Component should look like this:
<InputNumber step=".01" class="form-control form-control-xs" #bind-Value="#employee.Salary" #oninput="#((e) => #employee.Salary = Convert.ToDecimal(e.Value))" />
Now, whenever the input of your text box changes, the input event is triggered, and the ChangeEventArags is passed to you, you extract the value, convert it to decimal and assigned it to the #employee.Salary property.
This answer could be deduced from my first answer where I use
#oninput="#((e) => CalculationHere(e))"
to call the CalculationHere
Hope this helps...
The InputNumber component should be embedded in the EditForm Component whose Model attribute is set to your model employee
You should not add the #bind-Value:event="onkeydown". What for ? The default and the correct event for the binding is the onchange event and it deals appropriately with updating the Salary property.
Put this code in the Index page and run
<EditForm Model="#employee" OnValidSubmit="#HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" #bind-Value="#employee.Name" />
<!-- <InputNumber step=".01" class="form-control form-control-xs" #bind-Value="#employee.Salary" /> -->
<InputNumber step=".01" class="form-control form-control-xs" #bind-Value="#employee.Salary" #oninput="#((e) => CalculationHere(e))" />
<button type="submit">Submit</button>
</EditForm>
<p>Salary: #employee.Salary</p>
<p>After calculation: #calculation</p>
#code{
decimal calculation;
Employee employee = new Employee() { Name = "Davolio Nancy", Salary = 234 } ;
public class Employee
{
public string Name { get; set; }
private decimal salary { get; set; }
public decimal Salary
{
get
{
return salary;
}
set
{
salary = value;
//CalculationHere();
}
}
}
private void HandleValidSubmit()
{
}
void CalculationHere(ChangeEventArgs e)
{
calculation = Convert.ToDecimal(e.Value) * Convert.ToDecimal(1.2);
}
}

ASP.NET MVC checkbox always false

I made an asp.net website, but the checkbox is always false. Why is this so?
Model:
public string Username { get; set; }
public string Password { get; set; }
public bool Remember { get; set; }
CSHTML:
<div class="form-group">
#Html.Label("Remember me?")
#Html.CheckBoxFor(m => m.Remember)
</div>
The Remember property is always false, if the checkbox is checked then Rememberis still false.
I got the same issue, I fixed it by writing html checkbox tag, giving it the name same as property name, and value = true, if the checkbox is not checked no need to worry as it won't be submitted anyway,
in your case this will be it
<input type="checkbox" name="Remember" value="true" />
With Razor, I had the same problem. What worked for me was taking off the value="xxx" tag. Then it functioned normally.
Does not work:
<input class="form-check-input" value="true" asp-for="Answer.aIsCorrect" />
Works:
<input class="form-check-input" asp-for="Answer.aIsCorrect" />
The first parameter is not checkbox value but rather view model binding for the checkbox hence:
#Html.CheckBoxFor(m => m.SomeBooleanProperty, new { #checked = "checked" });
The first parameter must identify a boolean property within your model (it's an Expression not an anonymous method returning a value) and second property defines any additional HTML element attributes. I'm not 100% sure that the above attribute will initially check your checkbox, but you can try. But beware. Even though it may work you may have issues later on, when loading a valid model data and that particular property is set to false.
Source and additional info:
https://stackoverflow.com/a/12674731/3397630
Hope it will helpful for you ,kindly let me know your thoughts or feedbacks
Thanks
Karthik

ASP.NET - two types of users that register in one registration form?

I'm building a website application that will have two different types of users, let's call one A and the other is B. They have some similar data, such as: 'name', 'password', etc., and the rest are different. I have done 2 tables for them separately because I need it like that, but I have an idea and I'm not sure whether I can do it!
The idea is that when the user goes to the Registration Page, they will be shown a registration form that contains the data that is similar between A and B, and then I will let the user check a check box indicating whether it's an A user or a B user. Depending on what they have chosen, the rest of the form will appear in the same page to let them continue registration.
I'm working with ASP.NET in C# and I'm wondering whether this idea is applicable? My problem is with the check box - how do I let the rest of the registration form appear depending on what they have chosen, then add it to the right table?
MVC?
2 options:
Either have both of the forms in your html, with attribute ID = 'form a', 'form b'. Make sure to submit the forms to different actions.
Show hide either form like this:
$('.radioBtn').click(function() {
var formType = $(this).val();
//alert(formType);
if (formType == "A") {
$('#FormA').show();
$('#FormB').hide();
} else {
$('#FormB').show();
$('#FormA').hide();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<form style="display: none" id="FormA" action="/actionA">
.... your html FORM A
</form>
<form style="display: none" id="FormB" action="/actionB">
.... your html FORM B
</form>
<input type="radio" name="typeOfForm" class="radioBtn" value="A">Form A
<input type="radio" name="typeOfForm" class="radioBtn" value="B">Form B
Also, if you want to show the forms just don't do display:none
inside the form have a which is set to no display until a user makes a choice.
--
OR
Use ajax, have your forms as partial views and upload them into a target div once the radio is clicked. (let us know if this is needed)
I think the first show / hide is enough for your case. There is no reason to upload since the form is just an empty set of inputs.
EDIT
Next, we catch these submitted forms in your controller. Each form will submit to the same action, or you wish different actions, this does not make a difference - your preference.
option 1.
The form on the page:
<form action='#Url.Action("YourRegisterAction", "controller")' >
<input type="hidden" name="FormType" value="A"/> <!--place B for B form-->
<input type="text" name="Name" placeholder ="enter your name"/>
<input type="text" name="Password" placeholder ="enter your name"/>
<input type="submit" value="Register Me!"/>
</form>
The controller
[HttpPost]
public ActionResult YourRegisterAction(char formType, string name, string password)
{
if (formType == 'A')
bool success = BL.Server.Instance.SaveMyNewUserToDBTypeA(name, password);
else if (formType == 'B')
bool success = BL.Server.Instance.SaveMyNewUserToDBTypeB(name, password);
return View("ThankYou", success);
}
option 2.
Use models.
The model
public class YourRegisterAction
{
public string Name { get; set; }
public string Password { get; set; }
public char FormType { get; set; }
}
The view
#model Domain.UI.Models
<form action='#Url.Action("YourRegisterAction", "controller")' >
#Html.HiddenFor(m=>m.FormType)
#Html.TextBoxFor(m=>m.Name)
#Html.TextBoxFor(m=>m.Password)
<input type="submit" value="Register Me!"/>
</form>
The controller
[HttpPost]
public ActionResult YourRegisterAction(RegisterViewModel m)
{
if (m.FormType == 'A')
bool success = BL.Server.Instance.SaveMyNewUserToDBTypeA(m.Name, m.Password);
else if (m.FormType == 'B')
bool success = BL.Server.Instance.SaveMyNewUserToDBTypeB(m.Name, m.Password);
return View("ThankYou", success);
}
After you have the submitted form in your controller. Just persist in the DB as you normally would.
Also please use #using (Html.BeginForm) instead of the form tags. You can find plenty of info on this here.
Like #Fel said on Comment,
You should better use the radio buttons,
Let call them as rb1 and rb2, grouping the radio buttons by give them a same groupname.
And Also Give AutoPostBack="True" for both, So that only you can change the rest of the fields while the radiobutton is checked.
Create the rest of forms for both users separately as Panels p1 for A and p2 for B
In the rb1_checkedchanged event, show p1,
In the rb2_checkedchanged event, show p2
When click the Submit button
if (rb1.checked=true)
display form for A;
store it in a Table for A;
else
display form for B;
store it in a Table for B;
Hope this Helps...
All the Best...

Add element dynamically in MVC form

I am working on a asp.net mvc-5 project. I have following c# model:
public class Settings
{
public int Id { get; set; }
public string Name { get; set; }
public string Value { get; set; }
public int ParentId { get; set; }
public List<Settings> SubSettings { get; set; }
}
I am rendering this model on razor view by using EditorTemplates as explained here. Now i want to add remove Settings node dynamically like:
When we click on red button the element should get deleted (which is quite simple and i already implemented it) and when we click on green button the node should get added to its appropriate place (here i want your help).
The node should added is such a way that default model binder can map it to its right place, can anyone please explain me how can i do this?
The key to ensuring dynamically added elements post back correctly for binding is to use an indexer. One way to do this is to create the elements representing the new object, giving them a fake indexer (so this one does not post back) and then cloning the elements and updating the index. For example
View
<div id="NewSetting" style="display:none">
<tr>
<td><input type="text" name="Settings[#].ID value /></td>
<td><input type="text" name="Settings[#].Name value /></td>
<td>.....</td> // more properties of Settings
<td><input type="hidden" name="Settings[#].Index" value ="%"/></td>
</tr>
</div>
Note the use of a dummy indexer to prevent this one being posted back
Script
$(AddButton).click(function() {
var index = // assign a unique value
var clone = $('#NewSetting').clone();
// Update the index of the clone
clone.html($(clone).html().replace(/\[#\]/g, '[' + index + ']'));
clone.html($(clone).html().replace(/"%"/g, '"' + index + '"'));
$(SomeElement).append(clone);
}
Obviously change AddButton and SomeElement selectors to suit your needs.
You will also need to ensure your editor template for creating existing Settings include the Settings[].Index property.
I would recommend you not to add/delete the nodes but hide/show them.
Include all the possible nodes in your model and use jquery to show and hide when the buttons are clicked.
You can do this via Javascript. You can use jQuery to clone the an existing dom element then change the name. Or you could you a Ajax request to get the new HTML see this post for an example.
So you HTML/View need to contain a index for each dynamic item e.g.
<input type="checkbox" name = "Foo[0].Skills" value="true"/>
<input type="checkbox" name = "Foo[1].Skills" value="true"/>
<input type="checkbox" name = "Foo[2].Skills" value="true"/>
Alternatively you could use a JavaScript template engine to dynamically as new HTML form elements such as http://handlebarsjs.com/

Categories