ASP.NET MVC checkbox always false - c#

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

Related

How to update properties from object using input fields with onchange methods to write the data?

I'm trying to make a "Edit" section to edit objects and update them in the database:
First of all I obtain the current object and load input fields depending on PropertyType(string = textfield, int = number picker, etc):
Object:
Place input fields:
<EditForm #ref="EditForm" Model="ObjectType" novalidate>
<DataAnnotationsValidator />
#foreach (var property in EditObject.GetType().GetProperties())
{
#if (property.PropertyType.Name.Equals("String"))
{
<SfTextBox Placeholder="#property.Name"
Type="InputType.Text"
#onchange="#((Microsoft.AspNetCore.Components.ChangeEventArgs __e) => property.SetValue(EditObject, __e.Value))"
Value="#property.GetValue(EditObject, null)"
CssClass="create-model-item">
</SfTextBox>
}
else if (property.PropertyType.Name.Contains("Int"))
{
<SfNumericTextBox TValue="int?" Placeholder="Choose a Number Value="#property.GetValue(EditObject, null)" CssClass="create-model-item">
<NumericTextBoxEvents TValue="int?"
ValueChange="#((Syncfusion.Blazor.Inputs.ChangeEventArgs<int?> __e) => property.SetValue(EditObject, __e.Value))">
</NumericTextBoxEvents>
</SfNumericTextBox>
}
}
<SfButton OnClick="SendForm" IsPrimary="true" CssClass="mb-3">Create</SfButton>
</EditForm>
Now I want to change the data of the properties in "EditObject" to the new values that the user has filled in, this is done by the "OnChange" method:
#onchange="#((Microsoft.AspNetCore.Components.ChangeEventArgs __e) => property.SetValue(EditObject, __e.Value))"
However this is giving me this error:
Does anyone know what is going wrong?
Thanks in advance!:)
You don't have to specify the type of the event.
Your #onchange code needs to change to #onchange="#((__e) => { property.SetValue(EditObject, __e.Value); })"
That should stop the error.
There is a two-way binding support for Textbox component. Therefore, no additional method is needed to update new values to Model property. If you used two-way binding it will be updated by default. So, kindly try with #bind-Value attribute.
Also have a look at the below UG link.
UG link: https://blazor.syncfusion.com/documentation/textbox/data-binding/#two-way-data-binding

Convert text to always be uppercase in Blazor

I am trying to make my input text always be uppercase in a blazor input text field. I tried creating a custom InputText like the below but it doesn't update the binding (appears as uppercase but doesn't bind as such). What am I doing wrong here? Is there a better way?
#inherits InputText
<input #attributes="AdditionalAttributes"
class="#CssClass"
value="#CurrentValue"
#oninput="EventCallback.Factory.CreateBinder<string>(
this, __value => CurrentValueAsString = __value.ToUpper(), CurrentValueAsString.ToUpper())" />
Simplicity works for me.
<input type="text" oninput="this.value=this.value.toUpperCase()" #bind=CurrentValueAsString />
For simplicity and (in my opinion) UX reasons, let's assume that the user is allowed to type lowercase letters, but the application will ToUpper the input after they leave that field.
First, make a new component so we can reuse the logic. I called mine UppercaseTextInput.razor
<input value="#UserInput"
#onchange="async e => await OnChange(e)" />
#code {
[Parameter]
public string UserInput { get; set; }
[Parameter]
public EventCallback<string> UserInputChanged { get; set; }
private async Task OnChange(ChangeEventArgs e)
{
var upperCase = (e.Value as string).ToUpperInvariant();
await UserInputChanged.InvokeAsync(upperCase);
}
}
The private method OnChange gets called whenever the input loses focus. Change #onchange to #oninput to make this happen every keystroke.
Now you can use this component in another page or component. For example, in the index page:
#page "/"
<h1>Hello, world!</h1>
<UppercaseTextInput #bind-UserInput="UserInput" />
<p>You typed: #UserInput</p>
#code {
public string UserInput { get; set; } = "Initial";
}
In this example, I have "Initial" as the starting text, which will be printed inside the text box. As soon as you leave the element, the text inside will be transformed to be uppercase.
The benefit of using a component is that you can do a standard #bind- with your properties.
I was using an old reference to the input which was causing the error. There was a bug in the code though (if the input was null). The corrected version can be seen here:
#inherits InputText
<input #attributes="AdditionalAttributes"
class="#CssClass"
value="#CurrentValue"
#oninput="EventCallback.Factory.CreateBinder<string>(
this, __value => CurrentValueAsString = __value?.ToUpper(), CurrentValueAsString?.ToUpper())" />
The answer to this was easier than all the answers: it can be solved using CSS text-transform: uppercase;. This is all you needed and it doesn't take any processing power because it's included in the browser's engine.
I'm using MudBlazor.
I scratched my head for a while why the heck adding
Style="text-transform: uppercase;"
to <MudInput> is not working, even with !important attribute the default user agent style (text-transform: none;) was applied.
C# or JS seemed overkill for the task in my opinion.
What finally worked for me was adding
input {
text-transform: uppercase;
}
to the site's CSS sheet (index.css in my case).
This eventually overwritten the default user agent style.

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);
}
}

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/

Setting bool in ViewModel using RadioButtonFor?

I have a fairly complex form, but the problem I'm having is with a very basic part of it. I have a radio button group with two radio buttons to represent a true or false value for a bool within my view model. So I have a model like this:
public class MyViewModel {
public bool IsPOBox { get; set; }
}
Then within my view I have the following code to produce the radio buttons:
#Html.RadioButtonFor(m => m.IsPOBox, true, new { id = "togglePOBoxOn" }) #Html.Label("togglePOBoxOn", "PO Box")
#Html.RadioButtonFor(m => m.IsPOBox, false, new { id = "togglePOBoxOff" }) #Html.Label("togglePOBoxOff", "Street Address")
The problem is, when I submit this with "PO Box" selected, the IsPOBox property is being set to false instead of true. In fact, the property is set to false regardless of which radio button is selected.
Have I messed something up here?
It turns out ASP.NET MVC doesn't include disabled fields' values when you submit a form. The field was being disabled by a checkbox further up in the form. Annoying!
Edit:
After seeing #JohnSaunders' comment below I did a quick search for how I'm supposed to have an uneditable field, but still have the information submitted. It turns out you should use the readonly attribute. I learned something today!
i.e.
<input type="text" readonly />

Categories