Calculate values within #HTML.TextBoxFor (MVC) using JavaScript - javascript

I have four #Html.TextBoxFor as the code shows below
#Html.TextBoxFor(model => model.money, "money", new { #class = "required numeric", id = "money", Value = String.Format("{0:C}", Model.money )})
#Html.TextBoxFor(model => model.money2, "money2", new { #class = "required numeric", id = "money2", Value = String.Format("{0:C}", Model.money2 )})
#Html.TextBoxFor(model => model.money3, "money3", new { #class = "required numeric", id = "money3", Value = String.Format("{0:C}", Model.money3 )})
#Html.TextBoxFor(model => model.TotalMoney, "TotalMoney", new { #class = "required numeric", id = "TotalMoney", Value = String.Format("{0:C}", Model.TotalMoney )})
I previously used four
<input type="text" id="money" onkeyup="sum();" name="money" value="#Model.money" />
in order to add money, money 2 and money 3 together to produce a result in TotalMoney but it gives me a decimal problem and if I use TextBoxFor I don't get the decimal problem however I loose the calculation functionality.
JavaScript code I'm using is
<script type="text/javascript">
function sum() {
var txtFirstNumberValue = document.getElementById('money').value;
var txtSecondNumberValue = document.getElementById('money2').value;
var txtThirdNumberValue = document.getElementById('money3').value;
var result = parseFloat(txtFirstNumberValue) + parseFloat(txtSecondNumberValue) + parseFloat(txtThirdNumberValue);
if (!isNaN(result)) {
document.getElementById('TotalMoney').value = result.toFixed(2);
}
}
</script>
And the JS works great with input but won't work at all with TextBoxFor, how can I adapt the JS into my TextBoxFor?

I had to adapt Stephen's answer to work as I needed it too. Stephen's answer as shown below worked great as it allowed my values to be displayed as for example £15.15, thus removing the 2 decimal places. However the only problem was I still lost the functionality of adding money, money 2 and money 3 together to automatically produce a total in TotalMoney.
#Html.TextBoxFor(m => m.money, "{0:C}", new { #class = "required numeric" })
The slight change I made to Stephen's code is shown below. This removed the £ symbol however it also ensured my values retained 2 decimal places (i.e £13.12) and allowed my calculation functionality to work again.
#Html.TextBoxFor(model => model.money, "{0:0.00}", new { #class = "required numeric", onkeyup = "sum()" })

Related

Change EditorFor in time of change input

I want to change Editorfor that display already data from database when i change input
i will take output of input and split it and put result in 2 EditorFor
<input type="text" value="Set Date" id="reservationtim onchange=myFunction()>
#Html.EditorFor(model => model.StartDate, new { htmlAttributes = new { #class = "form-control" }, id = "startDate" })
#Html.EditorFor(model => model.EndDate, new { htmlAttributes = new { #class = "form-control" } , id = "endDate" })
and the function :
<script>
function myFunction() {
var date = document.getElementById("reservationtime").value;
var res = date.split("-");
model => model.StartDate = res[0];
document.getElementById("startDate") = res[0];
document.getElementById("endDate") = res[1];
}
</script>
You're trying to set the element reference itself to the value you want. Rather you need to set the value attribute of the element reference:
document.getElementById("startDate").value = res[0];
Also, it looks like you're trying to mix server-side and client-side code here. Remember that JavaScript is not processed until the document has already been processed by the server and returned to the client. Once you're client-side, all that exists is just the DOM, which is created by the browser based on the HTML document the server sent down. In other words, the fact that you used EditorFor or whatever is completely lost. All you have is the result (i.e. HTML) of that call to EditorFor.
You should first correct your HTML, as some attributes are not specified correctly.
<input type="text" value="Set Date" id="reservationtime" onchange="myFunction()">
#Html.EditorFor(model => model.StartDate, new { #class = "form-control" } )
#Html.EditorFor(model => model.EndDate, new { #class = "form-control" } )
I don't know why you are explicitly setting id for above two editors. they by default take property name as ID. so I would suggest following script for it.
<script>
function myFunction() {
var date = document.getElementById("reservationtime").value;
var res = date.split("-");
model => model.StartDate = res[0];
if(res.length>1) {
document.getElementById("StartDate").value = res[0];
document.getElementById("EndDate").value = res[1];
// if you still want to set ID properties instead of using default use following
// document.getElementById("StartDate").value = res[0];
// document.getElementById("EndDate").value = res[1];
}
}
</script>

C# asp.net mvc Set CheckBoxFor checked-property with Model-Value

In my form i have a chekbox and when i click the checkbox a textbox is enabled.
When i submit the form i got both values(checkbox and textbox)and the site refresh,after the refresh the checkbox is checked but the textbox is disabled but has the last insert value.
If i submit again without making something the textbox returns null and not the last insert value.
I want that the checkbox got the value from my model and change the behavior of the textbox disabled-property und if no new value will be insert,it should return the last insert value.
When i set the model property of false the checkbox is also checked.
Has anyone a idea what i can do ?
View:
#Html.TextBoxFor(m => m.FilterModel.FilterOrgNameValue, new { #class = "form-control", #id = "OrganisatioName", #disabled = "disabled" })
#Html.CheckBoxFor(m => m.FilterModel.FilterOrgNameIsCheckedValue, new { #class = "form-control", #id = "OrgNameChecked", #checked = (Model.FilterModel.FilterOrgNameIsCheckedValue ? "checked" : "unchecked")})
JavaScript:
$("#OrgNameChecked").click(function () {
$('#OrganisatioName').attr("disabled", $(this).is(':unchecked'));
});
Model:
public bool FilterOrgNameIsCheckedValue { get; set; }
Controller (Function which got called by submit):
public ActionResult Index(AdminOrganizationModel m)
{
AdminOrganizationModel model = new AdminOrganizationModel();
if(TempData["model"] != null)
{
m = (AdminOrganizationModel)TempData["model"];
}
if(m.FilterModel == null)
{
m.FilterModel = new AdminOrganizationFilterModel();
}
model = m;
OrganizationBusinessObject organizationBusinessObject = new OrganizationBusinessObject(DbContext);
var organizations = DbContext.GetAllEntitiesQueryable<Organization>();
organizations = FilterOrganizations(organizations, model);
InitializeLicenseList(1);
AdminOrganizationModelBuilder modelBuilder = new AdminOrganizationModelBuilder();
IList<AdminOrganizationModel> organizationsModels = modelBuilder.GetModelCollection(organizations);
model.Organizations = new AjaxGridFactory().CreateAjaxGrid(organizationsModels.AsQueryable(), 1, false, 10) as AjaxGrid<AdminOrganizationModel>;
return View(model);
}
Fields after submit
Simple Solution ;)
I added a simple if statement in the View:
<div class="col-sm-2">
#if (Model.FilterModel.FilterOrgNameIsCheckedValue)
{
#Html.TextBoxFor(m => m.FilterModel.FilterOrgNameValue, new { #class = "form-control", #id = "OrganisatioName"})
}
else
{
#Html.TextBoxFor(m => m.FilterModel.FilterOrgNameValue, new { #class = "form-control", #id = "OrganisatioName", #disabled = "disabled" })
}
</div>
I guess its not the best way but it works =)

NumericTextBox - Execute JS calculation as the user types numbers. Can it be done?

I have a numeric text box that allows entry for a unit price. As a user spins the number up, the unitPrice and the quantity are multiplied to create extended price.
What I need is if the user types the value to have the calculation occur as well, or as they type. Right now if they type the unitPrice the extendedPrice is not calculated until they tab or click somewhere else on the page.
Is there a way to do this?
I am pretty new to C#, but a long time developer. Thanks for any help.
<div class="form-group">
<div class="col-md-2">
#Html.LabelFor(model => model.UnitPrice, new { style = "width: 30px;" });
</div>
<div>
<div class="col-md-8">
#(Html.Kendo().NumericTextBox<int>()
.Name("unitprice")
.Events(e => e
.Change("calculateExtendedPrice")
.Spin("calculateExtendedPrice"))
.Decimals(2)
.Format("c")
.Min(0)
.Max(10000)
.Value(0)
.HtmlAttributes(new { style = "width: 20%" })
)
#Html.Label("Extended Price", new { style = "width: 100px;" })
<label id="extendedPrice" ></label>
</div>
</div>
</div>
The script:
function calculateExtendedPrice() {
var unitPriceControl = $("#unitprice").data("kendoNumericTextBox");
var unitPrice = unitPriceControl.value();
var quantityControl = $("#quantity").data("kendoNumericTextBox");
var quantity = quantityControl.value();
//alert(unitPrice);
if (quantity == null || unitPrice == null) {
return;
}
var extendedPriceCalc = quantity * unitPrice;
$("#extendedPrice").text(extendedPriceCalc);
}
I don't think Kendo UI has that functionality but you could do it with a keyup event handler in jQuery:
$('#unitprice').keyup(function() {
calculateExtendedPrice();
});

Selecting dropdown value shows a Textbox, but doesn't stores a value passed in it

my view contains
<div class="col-md-3 ">
#{
List<SelectListItem> deformitylevel = new List<SelectListItem>();
deformitylevel.Add(new SelectListItem { Value = "hip", Text = "Hip" });
deformitylevel.Add(new SelectListItem { Value = "knee", Text = "Knee" });
deformitylevel.Add(new SelectListItem { Value = "ankle", Text = "Ankle" });
deformitylevel.Add(new SelectListItem { Value = "other", Text = "Other" });
}
#Html.DropDownListFor(model => model.DeformityLevel, deformitylevel, "--Select Level -", new { #class = "form-control", #onchange = "showdeformitytextbox()", id = "deformitydropdown" })
#Html.ValidationMessageFor(model => model.DeformityLevel, "", new { #class = "text-danger" })
</div>
<div class="col-md-3">
#Html.EditorFor(model => model.DeformityLevel, new { htmlattributes = new { #class = "form-control", id = "deformitytextbox" ,style= "display:none"} })
</div>
My function is
function showdeformitytextbox() {
if ($("#deformitydropdown option:selected").text() == 'Other') {
$("#deformitytextbox").show();
}
else {
$("#deformitytextbox").hide();
}
}
When I select "Other" in dropdownlist it stores 'other' in the database instead of storing a value which is entered in #Html.EditorFor.
What I'm forgetting Help!!
As mentioned by others, to make this cleaner, it would be best if you separated the model fields for the drop down and the textbox. Even if you get it to work using the below code, it will lead to more work if you have to return to the page with the other value selected. That said, the following does properly submit the expected value in the textbox. The key concept is to set the dropdown to disabled as you submit.
Assuming your form has an id of submitForm specified as follows:
#using (Html.BeginForm("someActionName", "someControllerName", FormMethod.Post, new { #id="submitForm"}))
Then the following code will ensure that the drop down doesn't submit its value by intercepting the form submission:
$("#submitForm").submit(function () {
if ($("#deformitydropdown option:selected").text() === "Other") {
$("#deformitydropdown").attr("disabled", true);
} else {
$("#deformitydropdown").removeAttr("disabled");
}
});
I would change the names of your current controls and make a hidden form element for DeformityLevel. Then set its value in javascript based on DropdownList and textbox change events.
***Something like this (jq not verified, just for illustration)
<select id="DeformityLevel_DDL">
<option></option>
<option></option>
<option></option>
</select>
<input type="text" id="DeformityLevel_TB" />
<input type="hidden" id="DeformityLevel" name="DeformityLevel" />
<script>
$(document).ready(function () {
$('#DeformityLevel_DDL').change(function () {
if ($(this).val() != 'other') {
$('#DeformityLevel').val(this.val());
}
});
$('#DeformityLevel_TB').on('change', function () {
$('#DeformityLevel').val($(this).val());
});
});
</script>
Well, your function only display the #deformitytextbox input, when the value entered there changes you should also update the model property.
If the form submits automatically on select change you should use preventDefault.
Try now with TextBox, your parameter for htmlAttributes is incorrect. Try:
<div class="col-md-3 ">
#Html.DropDownList("DeformityLevel", deformitylevel, "--Select Level -", new { #class = "form-control", #onchange = "showdeformitytextbox()", id = "deformitydropdown" })
#Html.ValidationMessage("DeformityLevel", "", new { #class = "text-danger" })
</div>
<div class="col-md-3">
#Html.TextBox("DeformityLevel", null, new { #class = "form-control", id = "deformitytextbox", style = "display:none;" })
</div>
<script>
function showdeformitytextbox() {
if ($("#deformitydropdown option:selected").text() == 'Other') {
$("#deformitytextbox").show();
}
else {
$("#deformitytextbox").hide();
}
}
</script>

Dropdownlist onchanged - Trouble persisting ViewModel

I am a ASP.NET developer that is trying to get to grips with MVC.
I'm creating a register page and I have 3 dropdowns.
Now the first dropdown must load first go to load the countries. Based on that I load the provinces and then based on that I load the cities in that province.
The trouble I'm having is that on the first change it keeps my selected value but on the second onchange it seems as everything is lost.
I load the reigster view by just loading countries so long. then the javascript posts it to an action.
cshtml
<label class="col-md-3 col-xs-5 control-label">Country:</label>
<div class="col-md-9 col-xs-7">
#Html.DropDownListFor(x => x.CountryId, (IEnumerable<SelectListItem>)ViewBag.CountryItems, "Please Select", new { #class = "form-control select", #onchange = "CallChangefunc(this.value, null)" })
</div>
</div>
<div class="form-group">
<label class="col-md-3 col-xs-5 control-label">Province:</label>
<div class="col-md-9 col-xs-7">
#Html.DropDownListFor(x => x.ProvinceId, (IEnumerable<SelectListItem>)ViewBag.ProvinceItems, "Please Select", new { #class = "form-control select", #onchange = "CallChangefunc(null, this.value)" })
</div>
</div>
<div class="form-group">
<label class="col-md-3 col-xs-5 control-label">City:</label>
<div class="col-md-9 col-xs-7">
#Html.DropDownListFor(x => x.CityId, (IEnumerable<SelectListItem>)ViewBag.CityItems, "Please Select", new { #class = "form-control select" })
</div>
</div>
The javascript
function CallChangefunc(countryId, provinceId) {
window.location.href = "/Master/SetDropDowns?provinceId=" + provinceId + "&countryId=" + countryId ;
}
First one "Register" loads 1'st then SetDropDowns gets called onchanged.
I load the viewbags(SelectedItemLists) otherwise I get errors on refresh. is there a better way to code the viewbags to not have in two places?
[HttpGet]
public ActionResult Register()
{
IEnumerable<SelectListItem> CountryItems = BusinessAPI.CountryManager.GetAllCountries().Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name
});
ViewBag.CountryItems = CountryItems;
IEnumerable<SelectListItem> ProvinceItems = BusinessAPI.ProvinceManager.GetAllProvincesByCountryId(0).Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name
});
ViewBag.ProvinceItems = ProvinceItems;
IEnumerable<SelectListItem> CityItems = BusinessAPI.CityManager.GetAllCitiesByProvinceId(0).Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name
});
ViewBag.CityItems = CityItems;
return View();
}
public ActionResult SetDropDowns(string provinceId, string countryId)
{
IEnumerable<SelectListItem> CountryItems = BusinessAPI.CountryManager.GetAllCountries().Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name
});
ViewBag.CountryItems = CountryItems;
int countId = 0;
if (countryId == "null")
countryId = string.Empty;
if (TempData["CountryId"] == null)
{
if (!string.IsNullOrEmpty(countryId))
{
countId = Convert.ToInt32(countryId);
TempData["CountryId"] = countId;
}
}
else
countId = Convert.ToInt32(TempData["ProvinceId"]);
IEnumerable<SelectListItem> ProvinceItems = BusinessAPI.ProvinceManager.GetAllProvincesByCountryId(Convert.ToInt32(countId)).Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name
});
ViewBag.ProvinceItems = ProvinceItems;
int provId = 0;
if (provinceId == "null")
provinceId = string.Empty;
if (TempData["ProvinceId"] == null)
{
if (!string.IsNullOrEmpty(provinceId))
{
provId = Convert.ToInt32(provinceId);
TempData["ProvinceId"] = provId;
}
}
else
provId = Convert.ToInt32(TempData["ProvinceId"]);
IEnumerable<SelectListItem> CityItems = BusinessAPI.CityManager.GetAllCitiesByProvinceId(provId).Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name
});
ViewBag.CityItems = CityItems;
return View("Register");
}
The problem is that you don't tell them to be selected, modify your lists that have SelectListItem like the example below, to tell what item from list is Selected.
IEnumerable<SelectListItem> CountryItems = BusinessAPI.CountryManager.GetAllCountries().Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name,
Selected = ci.id.ToString() == countryId // if match the condition is selected
});
Also, to keep both listed selected you can modify your View.
Modify the javascript function to send always the countryId. Doing this the current country will be always selected, even when you change province.
function CallChangefunc(provinceId) {
var countries = document.getElementById("CountryId");
var countryId = countries.options[countries.selectedIndex].value;
window.location.href = "/Master/SetDropDowns?provinceId=" + provinceId + "&countryId=" + countryId ;
}
Notice that on first dropdown CallChangefunc(null), with this we tell that we don't have a province selected, which is true.
<div class="col-md-9 col-xs-7">
#Html.DropDownListFor(x => x.CountryId, (IEnumerable<SelectListItem>)ViewBag.CountryItems, "Please Select", new { #class = "form-control select", #onchange = "CallChangefunc(null)" })
</div>
On second dropdown we send CallChangefunc(this.value), with this we tell what province was selected to take cities and to keep the current value selected after postback. And because the countryId is always send it will remain unchanged.
<div class="col-md-9 col-xs-7">
#Html.DropDownListFor(x => x.ProvinceId, (IEnumerable<SelectListItem>)ViewBag.ProvinceItems, "Please Select", new { #class = "form-control select", #onchange = "CallChangefunc(this.value)" })
</div>

Categories