I'm scratching my head on why this two way binding does not work.
I'm binding to a string property on the page called result. This binding works for any initial values, and I see it set on my input text box.
But when I change the value programmatically to another value, the textbox still shows the old value. If I change the textbox value, the result property is also updated.
A small sample of the issue: https://blazorfiddle.com/s/t0t4wpsv
#page "/"
<input type="text" #bind-value=#result>
<input type="button" onclick="ChangeText" value="Submit" />
<p>#result</p>
#code {
protected string result = "Hello";
private void ChangeText()
{
result = "World";
}
}
Change your input control onclick event to:
<input type="button" #onclick="ChangeText" value="Submit" />
Related
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'm trying to capture the URL submitted when the page loads. When the page loads, it's appended with provided parameters to give me information i need save off. The issue is when I have the user fill in form fields and submit, the URL contains the handler method. What seems obvious is that I need to capture the URL before the form is submitted. I'm not familiar enough w/ Razor to understand if there's an event that fires on load, or how to accomplish this. Is there something simple like a page load event? Thanks!
1) Starts as: https://localhost:44384/sign
2) On submit takes the handler name: https://localhost:44384/Sign?handler=SubmitAndRedirect
<form method="post">
First name:<br>
<input type="text" name="firstname" autocomplete="on" maxlength="10" required><br>
Last name:<br>
<input type="text" name="lastname" autocomplete="on" maxlength="10" required><br>
Employee number:<br>
<input type="text" name="empnum" maxlength="10">
<br>
<br>I agree to the terms above:<br>
<input type="checkbox" name="check" required>
<button type="submit" asp-page-handler="SubmitAndRedirect">Submit and Redirect</button>
</form>
public ActionResult OnPostSubmitAndRedirect()
{
//Capture Form Data and Push to SQL DB
var firstname = Request.Form["firstname"];
var lastname = Request.Form["lastname"];
var empnum = Request.Form["empnum"];
bool isValidUser = ValidateUser(empnum, lastname);
if (isValidUser == true)
{
WriteToDB(firstname, lastname, empnum, url);
return Redirect(hardcoded);
}
else
{
return Redirect("/sign");
}
}
Model binding features of MVC might be what you're looking for. Take a look at this article.
See how it uses the EmployeeViewModel class and how the form gets posted to the action.
There is no protected void Page_Load(object sender, EventArgs e) in MVC as in Web Forms that I'm aware of.
Also check out jQuery's submit handler. Maybe this can allow you to capture some information and process it before submitting.
Thanks all. I was able to resolve adding a property on the C# side and then capture the request before the form was submitted by setting the property outside the form using inline code between paragraph tags.
<p>
#{
var QS = Request.QueryString.Value;
JT.query = QS;
}
#*<h1> #JT.query</h1>*#
</p>
I have a list In my view. For each row, I view button and I am passing Id value as hidden. But when I click any button it is passing wrong hidden value to the controller. Always it passes the first-row hidden value to the controller.
View:
#foreach (var list in Model)
{
<div>
<div > #( ((int)1) + #Model.IndexOf(list)).</div>
<div >#list.details</div>
<div class="col-md-2 row-index">
<button class="btn btn-link" type="submit" name="action:view" id="view">View</button>
<input type="hidden" name="viewId" id="viewId" value="list.WId" />
</div>
</div>
}
Controller:
[HttpPost]
[MultipleButton(Name = "action", Argument = "view")]
public ActionResult ViewDetail(string viewId)
{
return RedirectToAction("ViewDetails");
}
To get all values you need to change the input value type in your controller to array of strings.
I hope that this solution can help you
[HttpPost]
[MultipleButton(Name = "action", Argument = "view")]
public ActionResult ViewDetail(string[] viewId)
{
return RedirectToAction("ViewDetails");
}
if you want to get the exact value you need to duplicate the form within your foreach
in this case you should write somthing like this :
#foreach (var list in Model)
{
<div>
<div > #( ((int)1) + #Model.IndexOf(list)).</div>
<div >#list.details</div>
<div class="col-md-2 row-index">
<form ... > // complete your form attributes
<button class="btn btn-link" type="submit" name="action:view" id="view">View</button>
<input type="hidden" name="viewId" id="viewId" value="list.WId" />
</form>
</div>
</div>
}
Note : You should delete the global form
You should have one form for each row. then you submit that row.
Otherwise as you state it passes first value.
You are setting each value to the same element ID (which is invalid anyway) and name. When you submit your form (which would be more helpful to fully answer your question) it is finding the first element that matches that criteria and submitting it.
There are multiple ways to resolve this such as the already mentioned form per entry but the other preference would be to modify you button to a div and add a click handler to pass the specific value to a js function which would then submit to the controller. Its a preference choice regarding how tightly coupled you want your front end. But the main problem is your element naming convention.
I have a razor view (Framework 4.5, MVC 5) and an html input type=checkbox with the value equal to a model boolean value but instead of true or false it binds "value".
This is my code:
for (int index = 0; index < Model.Item1.Locations.Length; index++)
{
WSTupleOfInt32StringStringBoolean location = Model.Item1.Locations[index];
<div class="editor-field">
<input id="#string.Format("presentation.ServiceInfoes[{1}].Locations[{0}].Key", index, Model.Item2)" type="checkbox" value="#location.ThirdValue" name="#string.Format("presentation.ServiceInfoes[{1}].Locations[{0}].ThirdValue", index, Model.Item2)" />
</div>
<div class="editor-label">
<label for="#string.Format("presentation.ServiceInfoes[{1}].Locations[{0}].Key", index, Model.Item2)">#location.FirstValue</label>
#if (!string.IsNullOrEmpty(location.SecondValue))
{
<img alt="#location.SecondValue" src="#string.Format("//maps.google.com/maps/api/staticmap?center={0}&markers=color:blue|{0}&zoom=15&size=64x64&sensor=false", location.SecondValue)" />
}
</div><br />
}
The location.ThirdValue is the boolean property, debuging the property it's fine.. but in the HTML i get value="value" and not value="false".
What's happening?
See this Answer
Basically you want to use HTML.CheckBoxFor(model => model.booleanProperty)
Do this
<input id="#string.Format("presentation.ServiceInfoes[{1}].Locations[{0}].Key", index, Model.Item2)" type="checkbox" #(location.ThirdValue ? "checked" : "") name="#string.Format("presentation.ServiceInfoes[{1}].Locations[{0}].ThirdValue", index, Model.Item2)" />
The value is not setting checkbox to be checked or not, value has different function. For example if you set value to 'test' and check the checkbox, when you submit the form, you will see that instead of true value of submitted variable will be 'test';
you can do pretty cool stuff with it. For example you have 3 checkboxes on your form. all of them have the same name, but different values. when you submit the form, the result you get will be comma-separated string with values of checked checkboxes;
I have searched all the topics discussing this issue and cant seem to find one that explains the issue using Asp.net C#, everything is either javascript or MVC or PHP my reasoning for opening a new question regarding this.
I have 2 input control type checkbox
<input runat="server" type="checkbox" name="chkChildSexMale" id="chkChildSexMale" />
<input runat="server" type="checkbox" name="chkChildSexFemale" id="chkChildSexFemale"/>
<asp:Button ID="btnSaveCheckBoxes" runat="server" Text="Save CheckBox" OnClick="btnSaveCheckBoxes_Click" />
*EDITED**
protected void SaveCheckBoxes()
{
if (chkChildSexMale.Checked)
{
do something
}
else if (chkChildSexFemale.Checked)
{
do something else
}
}
Then in my button click event I call this method
protected void btnSaveCheckBoxes_Click(object sender, EventArgs e)
{
SaveCheckBoxes();
}
You should be using input type radio, not checkbox, for two mutually exclusive selections:
<input runat="server" type="radio" name="chkChildSex" value="male" id="chkChildSexMale" />
<input runat="server" type="radio" name="chkChildSex" value="female" id="chkChildSexFemale" />
When you use the same name attribute for two checkboxes, the second overrides the first. When you use the same name attribute for two radio buttons, it associates them and the value is the value of the checked item.
Although the id attribute is different for both checkboxes the name attribute is the same.
Also, the suggestion about using radio buttons makes the most sense based on what it looks like you're trying to do.
<input runat="server" type="radio" name="rdoChildSex" value="Male" />
<input runat="server" type="radio" name="rdoChildSex" value="Female" />
Again, I would recommend going with the radio button example above when you need to pick between one of two options. But if you want to get radio-like functionality for checkboxes you can try this...
<input runat="server" type="checkbox" name="chkChildSexMale" value="Male" OnCheckedChanged="Check_Clicked" />
<input runat="server" type="checkbox" name="chkChildSexFemale" value="Female" OnCheckedChanged="Check_Clicked"/>
void Check_Clicked(Object sender, EventArge e)
{
var checkbox = ((CheckBox)sender);
if (checkbox.Value == "Male")
{
chkChildSexFemale.Checked = false;
chkChildSexMale.Checked = true;
do something...
}
else
{
chkChildSexMale.Checked = false;
chkChildSexFemale.Checked = ;
do something else...
}
}
The code above should REALLY cover all your bases. It is even somewhat overkill. But is should work.
Try changing your code to the following:
if (chkChildSexMale.Checked == true)
{
do something
}
else if (chkChildSexFemale.Checked == false)
{
do something else
}
My issue was on page load I was using my data reader to set the checkboxes based on certain values. Which when I clicked my button click it was over writing my selected values with values from the database. So I Had to add the if (!Page.IsPostBack)
Giving the information I provided it would have been really hard to figure out that so I thank all for trying to help