I have a web page with two TextBoxFor fields that utilize Javascript autocomplete. With one of the fields, ClientUser, the response includes an integer and a string. The integer is then compared with another integer field on the page, ClientID, and if they match, the string is used in the autocomplete suggestions. The other field's response, WorkmateUser, is a string list immediately usable in the autocomplete.
The controller is being hit and returning the correct total list, then the correct Url/field needing validation is chosen, but the list needing validation is undefined for the ClientUser autocomplete field needing validation. What is the most efficient way to compare an integer field on the page with an integer returned for the autocomplete list? Thanks in advance!
Razor:
<div class="row">
<div class="col-lg-12">
#Html.LabelFor(m => m.WorkmateUser, "Workmate To Add", new { #class = "control-label" })
#Html.TextBoxFor(m => m.WorkmateUser, new { data_autocomplete_url = Url.Action("GetWorkmates"), #class = "form-control" })
</div>
</div>
<div class="row">
<div class="col-lg-8">
#Html.LabelFor(m => m.ClientID, "Firm To Include", "--Choose Firm--")
#Html.DropDownListFor(m => m.ClientID, StaticCache.GetClients(Model.UserID), new { #class = "form-control" })
</div>
</div>
<div class="row">
<div class="col-lg-8">
#Html.LabelFor(m => m.ClientUser, "Client To Add", new { #class = "control-label" })
#Html.TextBoxFor(m => m.ClientUser, new { data_autocomplete_url = Url.Action("GetAllClients"), #class = "form-control" })
</div>
</div>
Javascript:
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$('*[data-autocomplete-url]')
.each(function () {
var $url = $(this);
$(this).autocomplete({
source: $(this).data("autocomplete-url"),
response: function (data) {
if ($(this).data("autocomplete-url") == "/Message/GetAllClients") {
var aList = [];
for (var i = 0; i < data.length; i++) {//data.length is undefined!!!
if (data[i].ClientID == $("#ClientID").val()) {
aList.push(data[i].FirstName);
}
}
return bros;
}
else {
return data;
}
}
});
});
});
</script>
It's probably not the most elegant solution, but I ended up separating out the autocomplete call that needs validation into its own script and passing the additional variable into the controller to do validation on the back end. The following works:
Script:
<script>
$(document).on('keyup', '#ClientUser', function () {
var abID = $(this),
cID = $("#ClientID").val(),
cList = [];
$.ajax({
type: "GET",
url: '#Url.Action("GetAllClients", "Message")',
data: { term: abID.val(), clientID: cID },
success: function (data) {
for (var i = 0; i < data.length; i++) {
cList.push(data[i]);
}
},
error: function () {
alert("Client employeess could not be pulled.");
}
});
abID.autocomplete({
source: cList
});
});
</script>
Related
I am learning asp.net mvc 5.
My dropdownlistfor is working perfect and shows right field based on its value.
But the problem is when the page loaded first time it shows all field..
Problem is: I want default is showing nothing when the page first time loaded.
my cshtml:
<div class="form-group">
<div class="col-md-10">
#Html.DropDownListFor(m => m.PaymentMethod, ViewBag.PayTypeList as List<SelectListItem>, new { #class = "btn btn-primary btn-lg dropdown-toggle", #id = "PaymentId" })
<div id="PaypalButton">
<br/>
<script src="https://www.paypalobjects.com/api/button.js?"
data-merchant="braintree"
data-id="paypal-button"
data-button="checkout"
data-color="gold"
data-size="medium"
data-shape="pill"
data-button_disabled="true">
</script>
<!--data-button_type="paypal_submit"-->
</div>
<div id="EcheckForm">
<div class="form-group">
<div class="col-md-10">
#Html.TextBoxFor(m => m.VecInsNum, new { #class = "form-control input-lg", placeholder = "Vehicle Isurance Number", required = "required", tabindex = 18 })
#Html.ValidationMessageFor(m => m.VecInsNum, null, new { #class = "text-danger" })
</div>
</div>
</div>
</div>
And Js:
#section Scripts {
<script type="text/javascript">
$(document).ready(function () {
$('#PaymentId').change(function () {
var value = $(this).val();
if (value == '1') {
$('#PaypalButton').show();
$('#EcheckForm').hide();
} else if (value == '2') {
$('#PaypalButton').hide();
$('#EcheckForm').show();
} else {
$('#PaypalButton').hide();
$('#EcheckForm').hide();
}
});
});
When the page first time loaded:
When I select Paypal:
when I select E-check:
When I go back to Default:
First, create a function which contains hide methods inside it:
// hide all div options
function hideOnLoad() {
$('#PaypalButton').hide();
$('#EcheckForm').hide();
}
Then, call function above to hide all option div elements when page has loaded at first time and when default value being selected as given below:
$(document).ready(function () {
hideOnLoad(); // add this line
$('#PaymentId').change(function () {
var value = $(this).val();
if (value == '1') {
$('#PaypalButton').show();
$('#EcheckForm').hide();
} else if (value == '2') {
$('#PaypalButton').hide();
$('#EcheckForm').show();
} else {
hideOnLoad();
}
});
});
Simplified example: JSFiddle Demonstration
Tried a few different ways but can't get it right and now as you can see it's all mixed up! This JavaScript business is not the same as it was 15 years ago! Thank you.
#section scripts
{
<script>
$(function () {
$("#cut").click(function () {
if (m.Fixture.IsCut.checked = true)
{
m.Fixture.BackOdds.readOnly == false;
}
else
{
m.Fixture.BackOdds.readOnly == true;
}
});
});
</script>
}
<div class="form-group">
#Html.LabelFor(m => m.Fixture.BackOdds)
#Html.TextBoxFor(m => m.Fixture.BackOdds, new { #id = "BackOdds", #class = "form-control", #readonly = "readonly" })
</div>
<div class="checkbox">
<label>
#Html.CheckBoxFor(m => m.Fixture.IsCut, new { #id = "cut", #onchange = "AutoCalculateMandateOnChange(this)"}) Odds Cut?
</label>
</div>
You need to refer to your element (m.Fixture.IsCut and m.Fixture.BackOdds are not elements in your DOM)
$("#cut").click(function () {
$('#BackOdds').prop('readonly', !$(this).is(':checked'));
});
I am using cascading dropdownlist in asp.net mvc.
When a value is selected from the first dropdown, the list is shown in 2nd dropdown. When I select the value from the 2nd dropdown it shows in the dropdown, but after clicking the submit button it disappears showing "Select from List". Why?
View:
<div class="row form-group">
<div class="col-md-6">
#Html.LabelFor(model => model.Religion_Id, new { #class = "control-label" })
<div class="input-group">
<span class="input-group-addon" style="background:white">
<i class="fa fa-cloud" style="color:#179CDC;"></i>
</span>
#Html.DropDownListFor(model => model.Religion_Id, Model.Religion, "Select From List", new { #class = "form-control select2me", #id = "ddlReligion" })
</div>
#Html.ValidationMessageFor(model => model.Religion_Id, string.Empty, new { #class = "small text-danger text-uppercase" })
</div>
<div class="col-md-6">
#Html.LabelFor(model => model.Sect_Id, new { #class = "control-label" })
<div class="input-group">
<span class="input-group-addon" style="background:white">
<i class="fa fa-cloud" style="color:#179CDC;"></i>
</span>
<div id="Sects">
#Html.DropDownListFor(model => model.Sect_Id, new List<SelectListItem>(), "Select Form List", new { #class = "form-control select2me", #id = "ddlSect" })
</div>
</div>
#Html.ValidationMessageFor(model => model.Sect_Id, string.Empty, new { #class = "small text-danger text-uppercase" })
</div>
</div>
<script>
$(document).ready(function () {
loadSect();
});
var loadSect = function (flag) {
if ("undefined" == typeof (flag)) {
flag = true;
}
$.ajax({
type: "post",
url: '#Url.Action("GetSects", "MyProfile", new { area = "Candidate" })',
data: { religionId: $('#ddlReligion').val() },
datatype: "json",
traditional: true,
success: function (data) {
var district = "<select id='ddlSect' class='form-control text-uppercase select2me' name='Sect_Id'>";
district = district + '<option value="">Select From List</option>';
for (var i = 0; i < data.length; i++) {
district = district + '<option value=' + data[i].Value + '>' + data[i].Text + '</option>';
}
district = district + '</select>';
$('#Sects').html(district);
if (flag) {
setOption($('#Sects select')[0], $('#HSPEC_ID').val())
}
if (jQuery().select2) {
$('#Sects .select2me').select2({
placeholder: "Select an option",
allowClear: true
});
}
}
});
};
$('#ddlReligion').change(function () {
loadSect(false);
});
function setOption(selectElement, value) {
var options = selectElement.options;
for (var i = 0, optionsLength = options.length; i < optionsLength; i++) {
if (options[i].value == value) {
selectElement.selectedIndex = i;
return true;
}
}
return false;
}
You are not doing a ajax submit. OR Your are not setting the value of second drop down back after post
In your code, I don't see any ajax submit after you choose the second drop dwn and hit submit. So the problem is you are posting this form to controller and then the controller is returning the view back with the same posted data. Now in the Razor syntax for the second drop down you are using
#Html.DropDownListFor(model => model.Sect_Id, new List<SelectListItem>(), "Select Form List", new { #class = "form-control select2me", #id = "ddlSect" })
Here you can see you are setting the value of second drop down by empty list new List<SelectListItem>() and that is why the second drop down is empty.
Solution
Either use AJAX submit for your form. So that your UI remains unchanged.
Change your Razor syntax to this
#Html.DropDownListFor(model => model.Sect_Id, Model.District, "Select Form List", new { #class = "form-control select2me", #id = "ddlSect" })
So add a additional property called Districts and initially set this Model.District to be new List<SelectListItem>() and then in your form post method you just pass back the data as received and it will be rendered properly after submit.
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>
In my index.cshtml file I have a razor element (#Html.EditorFor) that's a text box. Javascript isn't recognizing the element. If I change the element type to a non-razor syntax then javascript can see it. Am I missing some syntax here.
index.cshtml
<div class="jumbotron">
<h1>my application</h1>
#using (Html.BeginForm("Results", "Home", FormMethod.Post))
{
<div class="form-group">
//javascript can't see mainpagequery
#Html.EditorFor(model => model.SearchQuery, new { htmlAttributes = new { #class = "form-control", id = "mainpagequery" }})
#Html.ValidationMessageFor(model => model.SearchQuery, "", new { #class = "text-danger" })
//javascript can see mainpagequery in the non razor element here
<input type="text" class="form-control" placeholder="Search" id="mainpagequery">
</div>
<button type="submit" class="btn btn-default">Search</button>
}
Here is my javascript. If I use razor then 'mainpagequery' is underlines because it can't see it, if I use html then it's fine. I know I'm hitting my javascript because I see the alert message pop up.
$(document).ready(function () {
console.log("ready!");
alert("mainpage autocomplete function entered");
var input = document.getElementById('mainpagequery');
var options = {
types: ['(cities)'],
componentRestrictions: { country: "us" }
};
var mainpagequery = new window.google.maps.places.Autocomplete(input, options);
});
In case of #Html.EditorFor your id get overriden to model's property name.
If you find element using f12 you will find it as follows. (Notice id "SearchQuery124" I just renamed it to something)
So in your case in make change like
$(document).ready(function () {
console.log("ready!");
alert("mainpage autocomplete function entered");
var input = document.getElementById('SearchQuery').value;
console.log(input);
var options = {
types: ['(cities)'],
componentRestrictions: { country: "us" }
};
var mainpagequery = new window.google.maps.places.Autocomplete(input, options);
});
Try this
Instead of #Html.EditorFor use
#Html.TextBoxFor(model => model.SearchQuery, new { #class = "form-control" , id = "mainpagequery"})