Im using a bootstrap datetimepicker to input appointment datetimes to a knockout viewmodel. the viewmodel has an object appointment which holds the observable values for all appointment object. Im sending the appointment to the controller via an ajax call, however after many null values for my dates i found that you must create a custom binding for the datepicker. after implementing the custom binding on the git page of the datepicker i am still receiving null values for both the start and end dates.
Have i implemented the custom binding incorrectly?
Code:
View:
<div class="form-horizontal">
<h4>Appointment</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Start, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="container">
<div class="row">
<div class='col-sm-3'>
<div class="form-group">
<div class='input-group date' id='startdatepicker'>
<input type='text' class="form-control" data-bind="date: appointment.start, format: 'DD MMM YYYY'" /><span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
</div>
</div>
#Html.ValidationMessageFor(model => model.Start, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.End, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="container">
<div class="row">
<div class='col-sm-3'>
<div class="form-group">
<div class='input-group date' id='enddatepicker'>
<input type='text' class="form-control" data-bind="date: appointment.end, format: 'DD MMM YYYY'" /><span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
</div>
</div>
#Html.ValidationMessageFor(model => model.End, "", new { #class = "text-danger" })
</div>
</div>
Scripts section at bottom of view
#section Scripts {
#Scripts.Render("~/bundles/jqueryval",
"/Scripts/ViewModels/AppointmentFormViewModel.js")
<script>
$(function () {
$('#startdatepicker').datetimepicker();
$('#enddatepicker').datetimepicker();
});
var viewModel = new AppointmentFormViewModel(#Html.HtmlConvertToJson(Model));
ko.applyBindings(viewModel);
</script>
}
Knockout viewmodel
function AppointmentFormViewModel(appointment) {
var self = this;
self.saveCompleted = ko.observable(false);
self.sending = ko.observable(false);
self.isCreating = appointment.id == 0;
self.appointment = {
id: appointment.id,
start: ko.observable(appointment.start),
end: ko.observable(appointment.end),
text: ko.observable(appointment.text),
clientid: ko.observable(appointment.clientid),
employeeid: ko.observable(appointment.employeeid),
roomid: ko.observable(appointment.roomid),
};
ko.bindingHandlers.date = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
ko.utils.registerEventHandler(element, 'change', function () {
var value = valueAccessor();
if (element.value !== null && element.value !== undefined && element.value.length > 0) {
value(element.value);
}
else {
value('');
}
});
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor();
var allBindings = allBindingsAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
var pattern = allBindings.format || 'DD/MM/YYYY';
var output = "-";
if (valueUnwrapped !== null && valueUnwrapped !== undefined && valueUnwrapped.length > 0) {
output = moment(valueUnwrapped).format(pattern);
}
if ($(element).is("input") === true) {
$(element).val(output);
} else {
$(element).text(output);
}
}
};
here is the appointment model object that was sent from the knockout viewmodel
as you can see the date time is not what was selected
Here is how it posted to server
is creating is a variable to determine whether the form is editing or creating an appointment
self.appointment.__RequestVerificationToken = form[0].value;
$.ajax({
url: (self.isCreating) ? 'Create' : 'Edit',
type: 'post',
contentType: 'application/x-www-form-urlencoded',
data: ko.toJS(self.appointment)
})
Related
In my application, previously I had issue with loading data to the partial view. With help I resolved that it. But still there is some issue here. Now when create the request I use this partial view to add data and image for user.
#model Asp_PASMVC.Models.GeneralItms
#using Asp_PASMVC.Infrastructure
#{
var z = Model.Attachment_Description;
var a = Model.Attachment_Amount;
var x = Model.Attachment;
}
<li style="padding-bottom:15px">
#using (Html.BeginCollectionItem("GeneralItmsList"))
{
#Html.HiddenFor(model => model.TempID)
<div class="form-horizontal" id="quickForm" novalidate="novalidate">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row">
<div class="col-md-5 col-sm-6">
<div class="form-group">
Select Item Description
<div class="col-md-10">
#Html.EditorFor(model => model.Attachment_Description, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Attachment_Description, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="form-group">
Attachment Amount
<div class="col-md-10">
<div class="input-group-prepend">
<span class="input-group-text">Rs.</span>
#Html.EditorFor(model => model.Attachment_Amount, new { htmlAttributes = new { #class = "form-control" } })
</div>
#Html.ValidationMessageFor(model => model.Attachment_Amount, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="form-group">
Attachment
<div class="col-md-10">
<input type="file" name="ImageData#(Model.TempID.ToString())" id="ImageData#(Model.TempID.ToString())" multiple="multiple" data-id="Img#(Model.TempID.ToString())" onchange="checkImage(this)" />
#Html.ValidationMessageFor(model => model.Attachment, "", new { #class = "text-danger" })
</div>
</div>
<img id="Img#(Model.TempID.ToString())" src="" alt="" width="100" height="100" class="ml-1" />
</div>
<button type="button" class="btn btn-danger" onclick="$(this).parent().remove();">Remove</button>
</div>
</div>
}
</li>
<script type="text/javascript">
$('.js-dropdown').select2({
width: '100%', // need to override the changed default
});
function checkImage(obj) {
var fileExtension = ['jpeg', 'jpg', 'png', 'gif', 'bmp'];
var ResponceImgId = $(obj).data('id');
if ($.inArray($(obj).val().split('.').pop().toLowerCase(), fileExtension) == -1) {
alert('error', 'Upload Error', 'Only .jpeg, .jpg, .png, .gif, .bmp formats are allowed.');
}
else {
var files = obj.files;
var reader = new FileReader();
name = obj.value;
reader.onload = function (e) {
$('#' + ResponceImgId).prop('src', e.target.result);
};
reader.readAsDataURL(files[0]);
}
}
</script>
When creating the request in the controller I have code like this
if (appRequest.GeneralItmsList != null)
{
foreach (GeneralItms item in appRequest.GeneralItmsList)
{
HttpPostedFileBase file = Request.Files["ImageData" + item.TempID];
item.Attachment = ConvertToBytes(file);
}
appRequest.General = new List<General>()
{
new General
{
GeneralItms = appRequest.GeneralItmsList,
}
};
}
and this method will convert the image to byte and pass to the controller to submit the data.
public ActionResult RetrieveImageG(int id)
{
var q = from temp in db.GeneralItms where temp.Id == id select temp.Attachment;
byte[] cover = q.First();
if (cover != null)
{
return File(cover, "image/jpg");
}
else
{
return null;
}
}
So Crete is working fine, and when in the edit view, I again called the same partial view to load the data inside the edit main view.
It's has 3 fields. Item Description , Amount and the attachment.
So It's loading the Item Description and amount properly, and it won't load the image again. Within the partial view I have put
#{
var z = Model.Attachment_Description;
var a = Model.Attachment_Amount;
var x = Model.Attachment;
}
to check is data passing to the view. attachment is shown in the Model.Attachment. But it won't show in the view. Can I get a help on this?
if you already happen to have the image loaded in your model: doing this way you can display the image
<img src="data:image;base64,#System.Convert.ToBase64String(Model.Attachment)" />
I am having a problem with jquery validation within a Modal/Partial View as it's conflicting with my main view. The main issue is with #Scripts.Render("~/bundles/jqueryval") as when I add it to my main view, the main form will no longer submit (doesn't hit the controller) as the validation is rejecting UK style dates (as you can see in my code, I am using DateITA to solve this problem in my Modal and submits with no issues)
I have tried moving #Scripts.Render("~/bundles/jqueryval") to the partial view & the main page will now submit, but it breaks my submit for the Modal. I have also tried naming the main view form & modal form to apply the validation to just the modal, but this hasn't helped.
Thanks
Main view
#model Puspers2.ViewModels.ContractViewModel
#{
ViewBag.Title = "Contract";
}
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "mainForm" }))
{
<div class="form-group form-inline datepickerWidth">
<div class='input-group date mydatepicker datepickerWidth'>
#Html.TextBoxFor(m => m.TblContract.OrderPlacedDate, new { title = "Order Placed Date", placeholder = "dd/mm/yyyy", #class = "form-control datepickerWidth", onclick = "this.select()", id = "orderPlacedDate" })
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class='form-group form-inline datepickerWidth'>
<div class='input-group date mydatepicker datepickerWidth'>
#Html.TextBoxFor(m => m.TblContract.ContractStartDate, new { title = "Contract Start Date", placeholder = "dd/mm/yyyy", #class = "form-control datepickerWidth", id = "contractStartDate", onclick = "this.select()" })
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<!--SAVE BUTTON-->
<br /><br /><br /><br />
<div class="form-group absolute">
<hr />
<button type="submit" class="btn btn-primary btn-lg saveButtonPadding" value="save" formaction="ContractUpdate" formmethod="post" id="saveButton">Save</button>
</div>
<!--SAVE BUTTON-->
}
<!--div to hold the Partial view that forms the modal-->
<div class="form-group">
#Html.Partial("_ContractContributionDetails")
</div>
<!--end div to hold the Partial view that forms the modal-->
#section scripts{
#Scripts.Render("~/bundles/jqueryval")
<script>
//Modal
$(document).on('click', '#SaveContractContribution', function () {
var $form = $('#modalForm')
.validate({
rules: {
TblContractContributionHistory_CommencementDeductions: {
dateITA: true
}
}
});
if ($form.valid()) {
$.ajax({
async: false,
type: 'POST',
url: 'ContractContributionHistoryAdd',
datatype: "json",
data: {
contractNumber: $("#contractNumber").val(),
commencementDeductions: $('#TblContractContributionHistory_CommencementDeductions').val(),
deductionsCategoryId: $('#deductionsCategory').val(),
numberOfContributions: $('#TblContractContributionHistory_NumberOfContributions').val(),
employeeContributionReference: $('#TblContractContributionHistory_EmployeeContributionReference').val(),
teamMember: $('#TblContractContributionHistory_TeamMemberId').val()
},
success: function (data) {
location.reload();
}
});
}
});
// >> JS snippet to handle datepicker functionality >>
$(function () {
$('.mydatepicker').datetimepicker({
locale: 'en-gb',
format: 'DD/MM/YYYY',
showTodayButton: true,
showClear: true,
})
.on('dp.hide', function () { // on hiding data picker, record associated entryfield to allow focus to be set when built-in blur happens
dateField = $(this).find('input');
$("#contractStartDate,#contractEndDate,#actualTerminationDate").trigger("change")
PickerClosing = true;
});
// on exit from date field, check if caused by picker closing. If Yes, set focus back in field
$('.mydatepicker input').blur(function (e) {
if (PickerClosing == true) {
PickerClosing = false;
dateField.focus();
}
});
});
// << JS snippet to handle datepicker functionality <<
</script>
}
Partial View
#model Puspers2.ViewModels.ContractViewModel
#Scripts.Render("~/Scripts/jquery-1.10.2.js")
#Scripts.Render("~/Scripts/jquery-3.3.1.js")
#Scripts.Render("~/scripts/jquery-ui-1.12.1.min.js")
#Scripts.Render("~/scripts/bootbox.js")
#Scripts.Render("~/Scripts/bootstrap.js")
#Scripts.Render("~/Scripts/respond.js")
#Scripts.Render("~/Scripts/moment.js")
#Scripts.Render("~/Scripts/moment-with-locales.js")
#Scripts.Render("~/Scripts/bootstrap-datetimepicker.js")
#{
}
#using (Ajax.BeginForm("ContractContributionHistoryAdd", "Home", new AjaxOptions
{ }, new { id = "modalForm" }))
{
<div>
<!-- Modal -->
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content modalContentDeductions">
<h2 class="modal-header">Add Deduction</h2>
<div class="modal-body">
<p class="dateLabels"><strong>Deductions Commenced On</strong></p>
<div class='form-group form-inline modalDatepickerWidth'>
<div class='input-group date mydatepicker modalDatepickerWidth'>
#Html.TextBoxFor(m => m.TblContractContributionHistory.CommencementDeductions, new { title = "Commencement Deductions", #class = "form-control inputSizeMedium" })
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div class='form-group'>
#Html.LabelFor(m => m.TblContractContributionHistory.DeductionsCategoryId, new { title = "Payment" })
#Html.DropDownListFor(m => m.TblContractContributionHistory.DeductionsCategoryId, new SelectList(Model.TblDeductionsCategoryLOOKUP, "DeductionsCategoryId", "Category"), "Select Option", new { #class = "form-control inputSizeMedium", #id="deductionsCategory"})
#Html.ValidationMessageFor(m => m.TblContractContributionHistory.DeductionsCategoryId)
</div>
<div class="form-group">
#Html.LabelFor(m => m.TblContractContributionHistory.EmployeeContributionReference, new { title = "Monthly Cost To Employee" })
#Html.TextBoxFor(m => m.TblContractContributionHistory.EmployeeContributionReference, new { title = "Monthly Cost To Employee", #class = "form-control inputSizeMedium" })
</div>
<div class="form-group">
#Html.LabelFor(m => m.TblContractContributionHistory.NumberOfContributions, new { title = "" })
#Html.TextBoxFor(m => m.TblContractContributionHistory.NumberOfContributions, new { title = "", #class = "form-control inputSizeMedium" })
</div>
<div class='form-group'>
#Html.LabelFor(m => m.TblContractContributionHistory.TeamMemberId, new { title = "" })
#Html.DropDownListFor(m => m.TblContractContributionHistory.TeamMemberId, new SelectList(Model.TblTeamMembersLOOKUP, "TeamMemberId", "TeamMemberName"), "Select Option", new { #class = "form-control inputSizeMedium" })
#Html.ValidationMessageFor(m => m.TblContractContributionHistory.TeamMemberId)
</div>
<br />
<div>
<button id="SaveContractContribution" class="btn btn-primary btn-lg" value="save" formmethod="post">Save</button>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
}
#section scripts
{
<script>
$(function () {
$.validator.unobtrusive.parse('#modalForm');
});
$(function () {
$('.mydatepicker').datetimepicker({
locale: 'en-gb',
format: 'DD/MM/YYYY',
showTodayButton: true,
showClear: true,
})
.on('dp.hide', function () { // on hiding data picker, record associated entryfield to allow focus to be set when built-in blur happens
dateField = $(this).find('input');
$("#contractStartDate,#contractEndDate,#actualTerminationDate").trigger("change")
PickerClosing = true;
});
// on exit from date field, check if caused by picker closing. If Yes, set focus back in field
$('.mydatepicker input').blur(function (e) {
if (PickerClosing == true) {
PickerClosing = false;
dateField.focus();
}
});
})
</script>
}
DateITA
$.validator.addMethod( "dateITA", function( value, element ) {
var check = false,
re = /^\d{1,2}\/\d{1,2}\/\d{4}$/,
adata, gg, mm, aaaa, xdata;
if ( re.test( value ) ) {
adata = value.split( "/" );
gg = parseInt( adata[ 0 ], 10 );
mm = parseInt( adata[ 1 ], 10 );
aaaa = parseInt( adata[ 2 ], 10 );
xdata = new Date( Date.UTC( aaaa, mm - 1, gg, 12, 0, 0, 0 ) );
if ( ( xdata.getUTCFullYear() === aaaa ) && ( xdata.getUTCMonth() === mm - 1 ) && ( xdata.getUTCDate() === gg ) ) {
check = true;
} else {
check = false;
}
} else {
check = false;
}
return this.optional( element ) || check;
}, $.validator.messages.date );
I'm trying to submit my form using Ajax.beginform. I tried everything but i am getting this resource cannot found error.
I have two models - PatientEligibility and PatientDetails. Both contains 10-12 properties respectively.
I have created on viewmodel using those two models and I am trying to use some of the properties in one partial view and submitting that data button click
my view -
#model Portal.Models.EligibilityViewModel
<script type="text/javascript">
$(document).ready(function () {
$('input[type="checkbox"]').on('change', function () {
$('input[name="' + this.name + '"]').not(this).prop('checked', false);
});
});
</script>
<div class="row margin-top-0">
<div class="col-xs-12 col-sm-12">
<h4><b>Patient Eligibility</b></h4>
</div>
</div>
#using (Ajax.BeginForm("SubmitPatientEligibility", "Ophthalmic", new AjaxOptions { OnSuccess = "OnSuccess", OnFailure = "OnFailure" }))
{
<div class="row margin-top-10">
<div class="col-xs-12 col-sm-12">
<div class="margin-top-10">
<div class="checkbox">
<label>
#Html.CheckBoxFor(model => model.PatientEligibility.IsAboveSixty, new { #Name = "cbAgeEligibility", htmlAttributes = new { id = "cbAbvSixty", #class = "form-control", Name = "group1[]" } })
The patient is 60 or over
</label>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-12">
<div class="margin-top-10">
<div class="checkbox">
<label>
#Html.CheckBoxFor(model => model.PatientEligibility.IsBelowSixteen, new { #Name = "cbAgeEligibility", htmlAttributes = new { id = "cbUnderSixteen", #class = "form-control", Name = "group1[]" } })
The patient is under 16
</label>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-12">
<div class="margin-top-10">
<div class="checkbox">
<label>
#Html.CheckBoxFor(model => model.PatientEligibility.IsBetweenForty, new { #Name = "cbAgeEligibility", htmlAttributes = new { id = "cbAbovenForty", #class = "form-control", Name = "group1[]" } })
The patient is 40 or over and is the parent/brother/sister/child of a person who has or has had gloucoma
</label>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-12">
<div class="margin-top-10">
<div class="checkbox">
<label>
#Html.CheckBoxFor(model => model.PatientEligibility.IsStudent, new { #Name = "cbAgeEligibility", htmlAttributes = new { id = "cbStudent", #class = "form-control", Name = "group1[]" } })
The patient is full time student aged 16, 17 or 18 at the establishment below.
</label>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-12">
<div class="margin-top-10">
<div class="checkbox">
<label>
#Html.CheckBoxFor(model => model.PatientEligibility.IsPrisoner, new { data_toggle = "collapse", data_target = "#dvseenNotseen", htmlAttributes = new { id = "cbPrisoner", #class = "form-control" } })
The patient is prisoner on leave from the prison detailed below
</label>
</div>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-12">
<div class="margin-top-10">
#Html.LabelFor(p => p.PatientBenefit.NINNumber)
#Html.EditorFor(model => model.PatientBenefit.NINNumber, new { htmlAttributes = new { #class = "form-control", autocomplete = "off" } })
</div>
</div>
<div class="col-xs-12 col-sm-12">
<div class="margin-top-10">
<label>DATE OF BIRTH</label>
#Html.TextBoxFor(model => model.PatientBenefit.DOB, new { #class = "form-control", autocomplete = "off", #id = "datetimepicker1" })
</div>
</div>
<div class="row margin-top-10">
<div class="col-xs-12 col-sm-3">
<button class="btn btn-default" name="btnBack">Previous</button>
</div>
<div class="col-xs-12 col-sm-9 text-right">
<button class="btn btn-default" name="btnBack">Save Draft</button>
<button class="btn btn-success fa fa-chevron-right icon-right" name="btnNext" type="submit">Next</button>
</div>
</div>
}
and my model is like this -
public class EligibilityViewModel
{
public PatientEligibility PatientEligibility { get; set; }
public PatientBenefit PatientBenefit { get; set; }
}
I am trying to call this method on submit of Next button -
public class OphthalmicController : Controller
{
[HttpPost]
public ActionResult SubmitPatientEligibility(EligibilityViewModel model)
{
return null;
}
}
i dont know why but i am getting this 500 error resource cannot found for this method.
What am I missing here?
I have 3 dropdownlists: Country, State and City. On change of Country dropdown, state dropdown has to populate for selected country, on change of state dropdown, city dropdown has to populate for selected state.
The fuctionality works when the dropdown values are changed from the UI. Now I want to populate the dropdowns with the selected values stored in the database. ie. If my database has values countryId=1, stateId=5, cityId=2 then my dropdown should populate accordingly. For which the dropdown onchanhge has to call directly when selected value is set to it. But the value is getting set for the first dropdown (country dropdown) but state and city does not set the values as country on change is not triggered.
Here is my code:
.cshtml
<div class="row clearfix">
<div class="col-lg-2 col-md-2 col-sm-4 col-xs-5 form-control-label">
<label>Country</label>
</div>
<div class="col-lg-2 col-md-2 col-sm-8 col-xs-7">
<div class="form-group">
<div class="form-line">
#Html.DropDownListFor(m => m.CountryId, (IEnumerable<SelectListItem>)ViewBag.country, "-- Please select --", new { #class = "form-control show-tick"} )
</div><label id="CountryListLable" style="color:red;"></label>
</div>
</div>
<div class="col-lg-1 col-md-1 col-sm-4 col-xs-5 form-control-label">
<label>State</label>
</div>
<div class="col-lg-2 col-md-2 col-sm-8 col-xs-7">
<div class="form-group">
<div class="form-line">
<select id="ddState" class="form-control show-tick">
<option>-- Please select --</option>
</select>
</div>
<label id="StateListLable" style="color:red;"></label>
</div>
</div>
<div class="col-lg-1 col-md-1 col-sm-4 col-xs-5 form-control-label">
<label>City</label>
</div>
<div class="col-lg-2 col-md-2 col-sm-8 col-xs-7">
<div class="form-group">
<div class="form-line">
<select id="ddCity" name="ddCity" class="form-control show-tick">
<option value="0">-- Please select --</option>
</select>
</div>
<label id="CityListLable" style="color:red;"></label>
</div>
</div>
</div>
Jquery:
$('#CountryId').change(function () {
//alert($(this));
var cN;
var UserType = $(this).data('type');
$('#ddState').selectpicker();
$('#ddState').empty();
$('#ddState').selectpicker('refresh');
$('#ddState').append("<option>-- Please select --</option>");
cN = $('#CountryId').val();
if (cN === '') {
return false;
} else {
$.ajax({
url: "/AdminUser/GetStatesForCountry?countryId=" + cN, success: function (result) {
console.log(result);
$.each(result, function (key, value) {
$('#ddState')
.append($("<option></option>")
.attr("value", value.stateId)
.text(value.stateName));
$('#ddState').selectpicker('refresh');
$('#ddState').selectpicker('val', "-- Please select --");
});
}
});
}
});
$('#ddState').change(function () {
var UserType = $(this).data('type');
$('#ddCity').selectpicker();
$('#ddCity').empty();
$('#ddCity').selectpicker('refresh');
$('#ddCity').append("<option>-- Please select --</option>");
cN = $('#ddState').val();
if (cN === '') {
return false;
} else {
$.ajax({
url: "/AdminUser/GetCitiesForState?StateId=" + cN, success: function (result) {
console.log(result);
$.each(result, function (key, value) {
$('#ddCity')
.append($("<option></option>")
.attr("value", value.cityId)
.text(value.cityName));
$('#ddCity').selectpicker('refresh');
$('#ddCity').selectpicker('val', "-- Please select --");
});
}
});
}
});
Controller code
var countryData = new List<CountryData>();
IEnumerable<SelectListItem> countryList = new List<SelectListItem>();
countryData = (List<CountryData>)HttpContext.Cache.Get("countryResponse");
if (countryData == null)
{
string response = Service.APIHelper_GET(StringConstants.GetCountryDetails);
if (!response.Equals("Internal Server Error."))
{
countryData = new JavaScriptSerializer().Deserialize<List<CountryData>>(response);
HttpContext.Cache.Insert("countryResponse", countryData);
}
}
countryList = countryData.Select(m => new SelectListItem() { Text = m.countryName, Value = m.countryId.ToString() });
ViewBag.country = countryList;//new SelectList(countryList);
public JsonResult GetStatesForCountry(int countryId)//get states for countryid = id
{
Session["CountryId"] = countryId;
return Json(getStateList(countryId), JsonRequestBehavior.AllowGet);
}
public List<State> getStateList(int countryId)
{
var stateList = new List<State>();
stateList = (List<State>)HttpContext.Cache.Get("StateResponseForCountry_" + countryId);
if (stateList == null)
{
var response = (List<CountryData>)HttpContext.Cache.Get("countryResponse"); //this wont b null bcz on page load putting country list to chache
foreach (var item in response)
{
if (item.countryId == countryId)
{
stateList = item.states;
}
}
HttpContext.Cache.Insert("StateResponseForCountry_" + countryId, stateList);
}
return stateList;
}
public JsonResult GetCitiesForState(int StateId)
{
var cityList = new List<City>();
cityList = (List<City>)HttpContext.Cache.Get("CityResponseForState_" + StateId);
if (cityList == null)
{
List<State> stateList = getStateList(Convert.ToInt32(Session["CountryId"]));
foreach (var item in stateList)
{
if (item.stateId == StateId)
{
cityList = item.cities;
}
}
HttpContext.Cache.Insert("CityResponseForState_" + StateId, cityList);
}
return Json(cityList, JsonRequestBehavior.AllowGet);
}
Here is the scenario for better understanding of my issue:
I have a create user page in which user will select from cascaded dropdowns (country, state, city) and save selected valued to database. The problem is in edit user, where I need to populate the dropdowns based on selected values. ie. I need to populate state dropdown with selected values from database.
UPDATE
With the help of #Sagar's solution I have managed to set selected value for the country dropdown. But the state and city dropdowns are still not getting set. Here is the updated code:
cshtml
<div class="row clearfix">
<div class="col-lg-2 col-md-2 col-sm-4 col-xs-5 form-control-label">
<label>Country</label>
</div>
<div class="col-lg-2 col-md-2 col-sm-8 col-xs-7">
<div class="form-group">
<div class="form-line">
#Html.DropDownListFor(m => m.CountryId, (IEnumerable<SelectListItem>)ViewBag.country, "-- Please select --", new { #class = "form-control show-tick" })
</div><label id="CountryListLable" style="color:red;"></label>
</div>
</div>
<div class="col-lg-1 col-md-1 col-sm-4 col-xs-5 form-control-label">
<label>State</label>
</div>
<div class="col-lg-2 col-md-2 col-sm-8 col-xs-7">
<div class="form-group">
<div class="form-line">
#Html.DropDownListFor(m => m.StateId, Enumerable.Empty<SelectListItem>(), "-- Please select --", new { #class = "form-control show-tick" })
</div>
<label id="StateListLable" style="color:red;"></label>
</div>
</div>
<div class="col-lg-1 col-md-1 col-sm-4 col-xs-5 form-control-label">
<label>City</label>
</div>
<div class="col-lg-2 col-md-2 col-sm-8 col-xs-7">
<div class="form-group">
<div class="form-line">
#Html.DropDownListFor(m => m.fKCityId, Enumerable.Empty<SelectListItem>(), "-- Please select --", new { #class = "form-control show-tick" })
</div>
<label id="CityListLable" style="color:red;"></label>
</div>
</div>
</div>
Jquery
$(document).ready(function () {
var countryId = $('#CountryId').val();
getStates(countryId);
var StateId = $('#StateId').val();
alert(StateId);/// here I am not getting correct value -- it passes stateId='-- Please select --'
getCities(StateId);
$('#CountryId').change(function () {
var countryId = $(this).val();
getStates(countryId);
});
$('#StateId').change(function () {
var StateId = $(this).val();
getCities(StateId);
});
});
function getStates(countryId) {
$('#StateId').selectpicker();
$('#StateId').empty();
$('#StateId').selectpicker('refresh');
$('#StateId').append("<option>-- Please select --</option>");
if (countryId === '') {
return false;
} else {
$.ajax({
url: "/AdminUser/GetStatesForCountry?countryId=" + countryId, success: function (result) {
console.log(result);
$.each(result, function (key, value) {
$('#StateId')
.append($("<option></option>")
.attr("value", value.stateId)
.text(value.stateName));
$('#StateId').selectpicker('refresh');
$('#StateId').selectpicker('val', "-- Please select --");
});
}
});
}
}
function getCities(stateId)
{
$('#fKCityId').selectpicker();
$('#fKCityId').empty();
$('#fKCityId').selectpicker('refresh');
$('#fKCityId').append("<option>-- Please select --</option>");
if (stateId === '') {
return false;
} else {
$.ajax({
url: "/AdminUser/GetCitiesForState?StateId=" + stateId, success: function (result) {
console.log(result);
$.each(result, function (key, value) {
$('#fKCityId')
.append($("<option></option>")
.attr("value", value.cityId)
.text(value.cityName));
$('#fKCityId').selectpicker('refresh');
$('#fKCityId').selectpicker('val', "-- Please select --");
});
}
});
}
}
You have to call the ajax on change as well as document ready then it will work fine:
Like:
Create Some common function to call it on both ready and change state:
function getCountryStates(countryId){
//your ajax to get states by country
}
$(document').ready(function () {
var countryId = $('#CountryId').val();
getCountryStates(countryId);
});
$('#CountryId').change(function () {
var countryId = $(this).val();
getCountryStates(countryId);
});
You have to follow the above same process to get cities of selected state.
This will work.
I have managed to solve the issue with the help of #StephenMuecke comments.
All I had to do was, to populate the dropdowns while passing the model to the view.
Code:
Model usersDetail = users.userDetail;
ViewBag.State = getStateList(usersDetail.CountryId).Select(m => new SelectListItem() { Text = m.StateName, Value = m.Id.ToString() });
ViewBag.City = getCityList(usersDetail.StateId).Select(m => new SelectListItem() { Text = m.CityName, Value = m.Id.ToString() });
return View(usersDetail);
and modified .cshtml to populate state and city from viewbag:
<div class="row clearfix">
<div class="col-lg-2 col-md-2 col-sm-4 col-xs-5 form-control-label">
<label>Country</label>
</div>
<div class="col-lg-2 col-md-2 col-sm-8 col-xs-7">
<div class="form-group">
<div class="form-line">
#Html.DropDownListFor(m => m.CountryId, (IEnumerable<SelectListItem>)ViewBag.country, "-- Please select --", new { #class = "form-control show-tick" })
</div><label id="CountryListLable" style="color:red;"></label>
</div>
</div>
<div class="col-lg-1 col-md-1 col-sm-4 col-xs-5 form-control-label">
<label>State</label>
</div>
<div class="col-lg-2 col-md-2 col-sm-8 col-xs-7">
<div class="form-group">
<div class="form-line">
#Html.DropDownListFor(m => m.StateId, (IEnumerable<SelectListItem>)ViewBag.State, "-- Please select --", new { #class = "form-control show-tick" })
#*<select id="State" class="form-control show-tick">
<option>-- Please select --</option>
</select>*#
</div>
<label id="StateListLable" style="color:red;"></label>
</div>
</div>
<div class="col-lg-1 col-md-1 col-sm-4 col-xs-5 form-control-label">
<label>City</label>
</div>
<div class="col-lg-2 col-md-2 col-sm-8 col-xs-7">
<div class="form-group">
<div class="form-line">
#Html.DropDownListFor(m => m.fKCityId, (IEnumerable<SelectListItem>)ViewBag.City, "-- Please select --", new { #class = "form-control show-tick" })
#*<select id="ddCity" name="ddCity" class="form-control show-tick">
<option value="0">-- Please select --</option>
</select>*#
</div>
<label id="CityListLable" style="color:red;"></label>
</div>
</div>
</div>
I am validating date input server side and adding ModelError if user input is invalid. Following is my code
public ActionResult EditOffer()
{
var offerID = Convert.ToInt64(Request.RequestContext.RouteData.Values["id"]);
using (joyryde_storeEntities context = new joyryde_storeEntities())
{
var objOffer = context.tbl_offer.Where(x => x.LNG_OFFER_ID == offerID).FirstOrDefault();
ViewBag.OfferID = offerID;
ViewBag.Header = "Edit " + objOffer.TXT_OFFER_TITLE;
ViewBag.ActionToPerform = "Edit";
if (System.IO.File.Exists(Server.MapPath(string.Format("~/assets/images/Stores/{0}/O_{1}_Small.jpg", Session["StoreID"], offerID))))
{
objOffer.TXT_OFFER_SMALL_PATH = string.Format("~/assets/images/Stores/{0}/O_{1}_Small.jpg", Session["StoreID"], offerID);
}
return View("AddOffer", objOffer);
}
}
[HttpPost]
public ActionResult EditOffer(tbl_offer modal, string Add, string Edit)
{
if (ModelState.IsValid)
{
using (joyryde_storeEntities context = new joyryde_storeEntities())
{
var offerID = Convert.ToInt64(Request.RequestContext.RouteData.Values["id"]);
if (!isOfferExist(modal.DAT_START_OFFER.Value.Date, modal.DAT_END_OFFER.Value.Date.AddHours(23).AddMinutes(59).AddSeconds(59).AddMilliseconds(999), Convert.ToInt64(Session["StoreID"]), offerID, Add, Edit, context))
{
// My Code
return RedirectToAction("AllOffers", "Store");
}
else
{
ModelState.AddModelError("DAT_START_OFFER", "Date Not Available"); // Here i am adding Modal Error For Date
if (Edit != null)
{
return RedirectToAction("EditOffer");
}
else
{
return RedirectToAction("AddOffer");
}
}
}
}
else
{
return RedirectToAction("EditOffer");
}
View
<div class="panel-body container-fluid">
#using (Html.BeginForm("EditOffer", "Store", FormMethod.Post, new { #class = "form-horizontal", enctype = "multipart/form-data" , id="offerForm"}))
{
#Html.AntiForgeryToken();
#Html.ValidationSummary(true);
<div class="form-group">
<label class="col-sm-3 control-label">Offer Title</label>
<div class="col-sm-6">
#Html.TextBoxFor(model => model.TXT_OFFER_TITLE, new { #class = "form-control", placeholder = "Offer Title", autocomplete = "off", name = "title" })
#Html.ValidationMessageFor(model => model.TXT_OFFER_TITLE, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Offer Banner</label>
<div class="col-sm-9">
<div class="image-container" style=" border: 1px solid #ccc; display: table;position:relative">
<a href="#editimage" data-toggle="modal" class="btn btn-sm btn-icon btn-inverse btn-round btn-image-edit" data-toggle="tooltip" data-original-title="Edit">
<i class="icon wb-pencil" aria-hidden="true"></i>
</a>
<div class="img-preview preview-lg">
<img id="image_upload_preview" src="#Url.Content(string.Format("~/assets/images/Stores/{0}/O_{1}_Small.jpg", Session["StoreID"], ViewBag.OfferID))" style="width:100%" alt="your image" />
</div>
</div>
<div class="input-group-file" style="margin-top:5px">
#Html.TextBoxFor(modal => modal.TXT_OFFER_SMALL_PATH, new { #class = "hide", #readonly = "true", width = "0", id = "filePath" })
#Html.ValidationMessageFor(modal => modal.TXT_OFFER_SMALL_PATH, "", new { #class = "text-danger" })
<span class="">
<span class="btn btn-success btn-small btn-file">
Upload Image <i class="icon wb-upload" aria-hidden="true"></i>
<input type="file" name="files" accept="image/*" multiple="" id="fileupload" onchange="showimagepreview(this)">
</span>
</span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Offer Detail </label>
<div class="col-sm-6">
#Html.TextAreaFor(model => model.TXT_OFFER_TEXT, new { #class = "form-control", placeholder = "Offer Text", autocomplete = "off", name = "text" })
#Html.ValidationMessageFor(model => model.TXT_OFFER_TEXT, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Valid For</label>
<div class="col-sm-4">
<div class="input-daterange" data-plugin="datepicker">
<div class="input-group">
<span class="input-group-addon">
<i class="icon wb-calendar" aria-hidden="true"></i>
</span>
#Html.TextBoxFor(model => model.DAT_START_OFFER, "{0:dd MMMM yyyy}", new { #class = "form-control from_date", placeholder = "Start Date", autocomplete = "off", name = "start" })
#Html.ValidationMessageFor(model => model.DAT_START_OFFER, "", new { #class = "text-danger" })
</div>
<div class="input-group">
<span class="input-group-addon">to</span>
#Html.TextBoxFor(model => model.DAT_END_OFFER, "{0:dd MMMM yyyy}", new { #class = "form-control to_date", placeholder = "End Date", autocomplete = "off", name = "end" })
#Html.ValidationMessageFor(model => model.DAT_END_OFFER, "", new { #class = "text-danger" })
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">Is Premium</label>
<div class="col-sm-4">
<div class="radio-custom radio-default radio-inline">
#Html.RadioButtonFor(model => model.INT_IS_PRIME, 1, new { #id = "ispremiumYes", name = "ispremium", #checked = "checked" })
<label for="ispremiumYes">Yes</label>
</div>
<div class="radio-custom radio-default radio-inline">
#Html.RadioButtonFor(model => model.INT_IS_PRIME, 0, new { #id = "ispremiumNo", name = "ispremium", })
<label for="ispremiumNo">No</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-6 col-sm-offset-3">
<button type="submit" name="#ViewBag.ActionToPerform" class="btn btn-primary">Submit </button>
<button type="reset" class="btn btn-default btn-outline">Reset</button>
</div>
</div>
#Html.Hidden("cropWidth", new { id = "cropWidth" })
#Html.Hidden("cropHeight", new { id = "cropHeight" })
#Html.Hidden("cropPointX", new { id = "cropPointX" })
#Html.Hidden("cropPointY", new { id = "cropPointY" })
#Html.Hidden("ImgSrc", new { id = "ImgSrc" })
}
<div class="modal fade" id="editimage" aria-labelledby="modalLabel" role="dialog" tabindex="-1">
<div class="modal-dialog" role="document" style="width:1024px;height:768px">
<div class="modal-content ">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="modalLabel">Crop the image</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-sm-9">
<div class="cropper text-center">
<img id="image" src="#Url.Content(string.Format("~/assets/images/Stores/{0}/O_{1}_Small.jpg", Session["StoreID"], ViewBag.OfferID))" style="max-width:730px;" alt="Picture">
</div>
</div>
<div class="col-sm-3">
<div class="docs-preview clearfix">
<div class="img-preview preview-lg"></div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
But Modal Error is not showing on view. What could be the cause ?
When you set your model error then you use RedirectToAction, what mean that you load new page, check in your debug, after that your code go back to GET method and everything is reloaded.
You have to return your View with model.
ModelState.AddModelError("DAT_START_OFFER", "Date Not Available");
if (Edit != null)
{
return View(modal); //if your model is object named modal
}
You didn't see any error because of RedirectToAction. You should use the "View" method. For example you can just write return EditOffer()
If you use return RedirectToAction("EditOffer"); the error will not been show it will be redirect to public ActionResult EditOffer(){} Action method, the [HttpGet] will be shown. To rectify this error, you should use View() method. like return View(); it return the error to the form data posted page.
[HttpPost]
public ActionResult EditOffer(tbl_offer modal, string Add, string Edit)
{
if (ModelState.IsValid)
{
using (joyryde_storeEntities context = new joyryde_storeEntities())
{
var offerID = Convert.ToInt64(Request.RequestContext.RouteData.Values["id"]);
if (!isOfferExist(modal.DAT_START_OFFER.Value.Date, modal.DAT_END_OFFER.Value.Date.AddHours(23).AddMinutes(59).AddSeconds(59).AddMilliseconds(999), Convert.ToInt64(Session["StoreID"]), offerID, Add, Edit, context))
{
// My Code
return RedirectToAction("AllOffers", "Store");
}
else
{
ModelState.AddModelError("DAT_START_OFFER", "Date Not Available"); // Here i am adding Modal Error For Date
if (Edit != null)
{
return View(modal);
}
else
{
return RedirectToAction("AddOffer");
}
}
}
}
else
{
ViewBag.OfferID = Here give the office id;
ViewBag.Header = "Edit " + objOffer.TXT_OFFER_TITLE;
ViewBag.ActionToPerform = "Edit";
ModelState.AddModelError("","Your Error Message"); // Here i am adding Modal Error For Date
return View(modal);
}
}