i'm trying to use a asp-for and a condition inside a component but i can't find a way to do that.
Here's my code
<label asp-for="#Model.Selected">
#Model.Nome
<input type="checkbox" asp-for="#Model.Selected" />
</label>
and I wanna some like
<label asp-for="#Model.Selected">
#Model.Nome
<input type="checkbox" asp-for="#Model.Selected" #((Model.Unlucky) ? "disabled") />
</label>
How can i do this in ASP.Net Razor
I think you can add a new variable after that one and build the string to disable the input:
#{
var disabledTag = Model.Unlucky == null ? "disable" : "";
}
<input type="checkbox" asp-for="#Model.Selected" #disabledTag) />
Assumed that you're using Core MVC, you have two options to set disabled attribute conditionally inside <input> tag helper. Here are those options:
Option 1 - Using HTML helper
Create a static class which returns HtmlString to set disabled attribute with ternary operator:
public static class HtmlExtensions
{
public static IHtmlContent SetDisabled(this IHtmlHelper helper, bool value)
{
return new HtmlString(value ? #"disabled=""disabled""" : "");
}
}
And then use that helper inside Razor view:
<input type="checkbox" asp-for="#Model.Selected" #Html.SetDisabled(Model.Unlucky) />
Option 2 - Create Tag Helper Attribute
You can build a custom class derived from TagHelper instance and specify target element to add disabled attribute:
[HtmlTargetElement("checkbox")]
public class DisabledCheckBox : TagHelper
{
[HtmlAttributeName("asp-disabled")]
public bool IsDisabled { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (IsDisabled)
{
var d = new TagHelperAttribute("disabled", "disabled");
output.Attributes.Add(d);
}
base.Process(context, output);
}
}
Then you could use that attribute inside tag helper:
<input type="checkbox" asp-for="#Model.Selected" asp-disabled="#Model.Unlucky" />
Notes:
1) For both options, make sure that you've tag helper support enabled inside _ViewImports.cshtml, by checking existence of these lines below:
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#addTagHelper *, YourProjectNamespace
2) disabled attribute is a boolean attribute which when exist, it disabled the input element no matter what value it has. Therefore, disabled attribute must be absent if you want to keep it enabled.
You need a ternary operator. You can use it like this. Assuming Model.Unluck is a string, otherwise you need to use ToString() on it because both results must be of the same datatype.
<input type="checkbox" asp-for="#(Model.Selected ? Model.Unluck : "disabled")" />
If Model.Unluck is the boolean for the operator, then you do this.
<input type="checkbox" asp-for="#(Model.Unluck ? "enabled" : "disabled")" />
<input type="checkbox" asp-for="#(Model.Unluck ? "true" : "false")" />
You don't need any ternary operations or custom tag helpers to make element disabled in razor.
You can just use:
<input disabled="#Model.Unlucky" />
It will render <input disabled="disabled" /> if Model.Unlucky is true, and will omit disabled attribute completely if Model.Unlucky is false.
It also can be used with readonly or any other attributes where you need such behavior.
The trick here is that attribute value should have boolean type to be interpreted this way. For example if #Model.Unlucky is a string "true", it will just render as is disabled="true".
Related
Is there a way to make an input visible based on a bool variable?
<input type="button" value="Smth" onclick="...">
I am trying to find an HTML helper for this purpose, however no luck so far.
You can achieve your required result to set your input field as disabled by using the ternary conditional operator:
<input type="button" value="Smth" onclick="..." #(myBoolCondition == "true" ? "disabled='disabled'" : "") >
Where myBoolCondition is your variable holding the result of your condition.
try this
#if ( your bool condition)
{
<input type="button" value="Smth" onclick="..."> //visible
}
else
{
<input type="button" class="d-none" value="Smth" onclick="..."> //none-visible
//or
<input type="button" hidden value="Smth" onclick="...">
}
I feel this may be an easy fix but I cannot seem to get around it. I have an ASP.NET Core web application and I'm using an ajax form to submit data to my controller for processing. The problem I have is that my checkboxes always pass in as "false" even though they may be checked.
I searched for some answers but nothing I've tried has worked. Things like using the checked property, ensuring the name is correct.
Can anyone shed some light on why the values are ignored when the form is submitted to the controller and how I can fix it?
Form
<form asp-action="CreateCustomView" asp-controller="Data"
data-ajax="true"
data-ajax-method="POST">
<div class="row">
<div class="col">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="ColName" name="ColName" checked>
<label class="custom-control-label" for="ColName">Name</label>
</div>
</div>
<button type="reset">Reset</button>
<button type="submit">Save changes</button>
</form>
Model
namespace MyProject.Data
{
public class GridView : BaseEntity
{
public string Name { get; set; }
public bool ColName { get; set; }
}
}
DataController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MyProject.Data;
using Microsoft.AspNetCore.Mvc;
namespace MyProject.UI.Controllers
{
public class DataController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult CreateCustomView(GridView data)
{
//This method is incomplete, there is a break at the ActionResult to see what values are passed into `data`. In production, the values would be handled and the changes would be saved.
return View();
}
}
}
I have a breakpoint on the method CreateCustomView to see what values are passed, no matter what checkboxes I check, they are always being passed as false.
Can anyone help with this rather strange problem?
Update
As per the answer supplied by #Reyan-Chougle, if you're using CORE you need to supply the input as follows:
<input asp-for="#Model.ColType" type="checkbox" />
When the page is rendered, the control is automatically given a hidden field. Here is what the HTML of the above control renders as:
<input type="checkbox" class="custom-control-input" id="ColType" value="true" data-val="true" data-val-required="The ColType field is required." name="ColType">
<input type="hidden" value="false" id="ColType" name="ColType">
As you can see it creates a hidden checkbox with a value of false. This means that, as a boolean type it always has a value of true or false on submission.
As you are using ASP.NET Core, it is recommend to use the Tag Helpers:
<div class="form-group">
<label asp-for="#Model.ColName"></label>
<input asp-for="#Model.ColName" type="checkbox" />
</div>
If not using asp-for attribute , you can modify your codes to add a hidden field. It will be submitted regardless whether the checkbox is checked or not. If the checkbox is checked, the posted value will be true,false. The model binder will correctly extract true from the value. Otherwise it will be false :
<input type="checkbox" class="custom-control-input" data-val="true" id="ColName" name="ColName" value="true" checked>
<label class="custom-control-label" for="ColName">Name</label>
<input name="ColName" type="hidden" value="false">
I ran into a similar issue. There is a form we have that contains many fields that include textboxes, select (dropdown) menus, checkboxes and of course labels. All fields save to the database properly EXCEPT for the three checkbox options we have. I just figured out the fix after fooling with it off and on for weeks. I hope this helps someone:
This is what the code used to look like:
$(this).attr('data-val', 'true');
This is what fixed the problem:
$(this).val(true);
Here is the whole function that includes the fix:
$('form').on('change', ':checkbox', function () {
if (this.checked) {
$(this).val(true);
}
else {
$(this).val(false);
}
});
try to use
#Html.CheckBox("ColName", true)
I have a model which has a boolean property. In the edit view it displays as a text field of type text which I don't understand. In the documentation it states that a boolean input should display a checkbox for the type.
Model:
public class Person
{ ...
public bool? boolprop {get; set;}
}
Edit.cshtml:
{ ...
<div class="form-group">
<label asp-for="boolprop" class="control-label"></label>
<input asp-for="boolprop" class="form-control" />
<span asp-validation-for="boolprop" class="text-danger"></span>
</div>
}
Generated html:
<input class="form-control" type="text" id="boolprop" name="boolprop" value="True">
Any ideas how you can get a checkbox to display with the input tag helper?
You can get a tri-state list (not set, true, false) by doing this instead:
Html.InputFor(x=>x.boolprop)
A nullable boolean (bool?) and a boolean are not the same thing, of course. I agree the tag-helper output isn't especially intuitive, but Microsoft has said this is by design:
https://github.com/aspnet/Mvc/issues/5667#issuecomment-271394567
It's by design.
Imagine for example what it would mean for a bool? property to result in a checkbox . How could a user choose null when they submit a form?
I have this HTML
<div class="Radio">
<label>
<input class id="checkbox" name="category" type="radio" value="1">
<strong> TONY STARK </strong>
</label>
<label>
<input class id="checkbox" name="category" type="radio" value="2">
<strong> IRON MAN </strong>
</label>
<label>
<input class id="checkbox" name="category" type="radio" value="3">
<strong> ROBERT DOWNEY </strong>
</label>
I need to select radio buttons based on TONY STARK , IRON MAN , ROBERT DOWNEY as the user passes it as a flexible parameter
I tried this, but any other easy way would definitely help me!
driver.FindElement(By.Id("checkbox"));
for(WebElement radiobutton: radiobuttons)
{
if(radiobutton.getAttribute("value").equals("TONY STARK"))
radiobutton.click();
}
You should try using Xpath to get single radio button and avoid looping as below :-
string Xpath = ".//input[following-sibling::strong[contains(.,'TONY STARK')]]";
Or
string Xpath = ".//label[contains(.,'TONY STARK')]/input";
Use any one of these Xpath to find radio button as :
var radio = driver.FindElement(By.Xpath(Xpath));
radio.Click();
You can use xpath to do that. Try the below xpath .//label[contains(text(),'TONY STARK')]/input[#id='checbox']
Create a class to wrap up radios from now on:
public class RadioButtons
{
public RadioButtons(IWebDriver driver, ReadOnlyCollection<IWebElement> webElements)
{
Driver = driver;
WebElements = webElements;
}
protected IWebDriver Driver { get; }
protected ReadOnlyCollection<IWebElement> WebElements { get; }
public void SelectValue(String value)
{
WebElements.Single(we => we.GetAttribute("value") == value).Click();
}
}
Then you can use it like this:
RadioButtons categories = new RadioButtons(Driver, driver.FindElements(By.Name("category")));
categories.SelectValue("TONY STARK");
I have this other solution:
public void RadioButtonClickByNameAndValue(string name, string val)
{
ScreenComponent.Wait.WaitVisibleElement(By.Name(name));
ScreenComponent.Script.ExecuteJavaScriptCode($"$('[name={name}][value={val}]').click();");
}
In another class I say what value I want to click and in another class I say what is the element.
in my case the radio options value are "True" and "False".
Identify a radio button using XPath with index
IWebElement radioButton = driver.FindElement(By.XPath("//*[#type='radio'][1]");
radioButton.Click();
where:
Asterisk * means wildcard character.
[1] is the position of radio button options ("TONY STARK")
I have a form in my asp.net mvc view as follow:
<%using (Html.BeginForm("SearchBorrowed", "Admin", FormMethod.Get))
{ %>
<%: Html.TextBox("searchTerm", Request.QueryString["searchterm"])%>
<input type="submit" value="Search" />
<br />
Is Returned :
<%:Html.CheckBox("IsReturned")%>
<%} %>
and here is the 'SearchBorrowed' action:
public ActionResult SearchBorrowed(bool IsReturned=false, string searchTerm = null)
{
IEnumerable<BorrwoinfInfo> bs;
//...Get from repository
return View(bs.ToList());
}
and finally routing settings :
routes.MapRoute(
"SearchBorrowed", // Route name
"{controller}/{action}/{*searchTerm}", // URL with parameters
new
{
controller = "Admin",
action = "SearchBorrowed",
searchTerm = UrlParameter.Optional
} // Parameter defaults
when I submit the form without checking 'IsReturned' Checkbox,
it returns result and the url gets as follow :
.../SearchBorrowed?searchterm=&IsReturned=false
But when I check IsReturned' Checkbox, the urls gets like this:
.../SearchBorrowed?searchterm=s&IsReturned=true&IsReturned=false
Why there is two IsReturned in above url ?!
How Could I fix this ?
Why there is two IsReturned in above url ?!
Because the Html.CheckBox helper generates an additional hidden input field with the same name as the checkbox. If you look at the generated HTML you will see that the helper generated the following 2 input fields:
<input type="checkbox" name="IsReturned" id="IsReturned" value="true" checked="checked" />
<input type="hidden" name="IsReturned" id="IsReturned" value="false" />
This is by design. This helper is intended to be bound to a boolean property on your view model. When a checkbox field is not checked no value is sent to the server, so if there was not no hidden field you wouldn't be able to bind it to a boolean field.
If you don't want this hidden field you could either write a custom helper or generate the checkbox field manually.