Modal/Partial view uk date conflict MVC5 - c#

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

Related

Validation not firing in modal popup

My Validation is not firing on my popup its showing the popup just fine just not doing the validation
<div>
<form id="myForm">
#Html.HiddenFor(m => m.Id)
#Html.TextBoxFor(model => model.Name, new { #class = "form-control", #placeholder = "Name" })
<span asp-validation-for="#Model.Name" class="text-danger"></span>
#Html.TextBoxFor(model => model.Resitance, new { #class = "form-control", #placeholder = "Address" })
<span asp-validation-for="#Model.Resitance" class="text-danger"></span>
#Html.TextBoxFor(model => model.Passed, new { #class = "form-control", #placeholder = "Passed" })
<span asp-validation-for="#Model.Passed" class="text-danger"></span>
<select asp-for="CirtcutType"
asp-items="#Html.GetEnumSelectList(typeof(ElectricalSurvey.DAL.Models.CircuitModel.CirtcutTypes))"
class="form-control"></select>
<div class="modal-footer">
#if (Model.Id > 0) {<span>Update</span> } else {<span>Save</span>}
</div>
</form>
<div style="text-align:center;display:none" id="loaderDiv">
<img src="~/Content/InternetSlowdown_Day.gif" width="150" />
</div>
</div>
<script>
$(document).ready(function () {
$("#btnSubmit").click(function () {
$("#loaderDiv").show();
var myformdata = $("#myForm").serialize();
$.ajax({
type: "POST",
url: "/Electrician/SaveCircuit",
data: myformdata,
success: function () {
$("#loaderDiv").hide();
$("#MyEditUpateModal").modal("hide");
window.location.href = "/Electrician/Index";
}
})
})
})
_ValidationScriptsPartial.cshtml
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
To Note I am handing the dialog in html via following method.
<script>
var AddOrUpdateCircuit = function (id) {
var url = "/Electrician/AddOrUpdateCircut?id=" + id;
$("#myModalBodyDiv1").load(url, function () {
$("#MyEditUpateModal").modal("show");
})
}
This one will help you get started
<form id="myForm" class="needs-validation" novalidate>
and
$("#btnSubmit").click(function (e) {
e.preventDefault(); // do not execute actual submit.
var form = $("#myForm")[0];
form.classList.remove('was-validated');
if (form.checkValidity() === false) {
form.classList.add('was-validated');
return;
}
$.ajax({
//perform ajax
});
})

reCAPTCHA not visible in a MVC partialview page

I'm having troubles adding google reCAPTCHA to my page.
in the Layout I have added the Google Recaptcha js
_layout
<title>#ViewBag.Title</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
<script src='https://www.google.com/recaptcha/api.js'></script>
<script type="text/javascript">
<script type="text/javascript">
$(document).ready(function () {
$('#subject').on("change", function (e) {
e.preventDefault();
var selectedVal = $('#subject').val();
$.ajax({
// url: "/ContactUs/GetForm",
url: '#Url.Action("GetForm", "ContactUs")',
type: "POST",
data: { searchValue: selectedVal } ,
async: true,
success: function (data) {
$('#renderForms').empty();
$('#renderForms').append(data);
},
error: function (xhr, ajaxOptions, thrownError) {
alert("An error has occured!!! " + xhr.status + " && " + xhr.responseText);
}
});
});
});
</script>
then in my index I select which form I want to show:
#Html.DropDownListFor(model => model.contactSelectListItems, new List<SelectListItem>
{
new SelectListItem() {Text = "option1", Value="option1"},
new SelectListItem() {Text = "option2", Value="option2"},
new SelectListItem() {Text = "option3", Value="option3"},
}, "--Choose--", new { id = "subject", #class= "dropdown-item" })
</div>
<div id="renderForms">
</div>
in both partial page there is a form where I do something similiar yet different viewmodels:
#using (Html.BeginForm("SendCustomerTeam", "ContactUs", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>CustomerTeamViewModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="container">
<div class="form-group form-group-sm col-sm-6">
<div class="row">
#Html.LabelFor(model => model.Phone, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-sm-9">
#Html.EditorFor(model => model.Phone, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Phone, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group form-group-sm col-sm-12">
<div class="row">
#Html.LabelFor(model => model.Inquiry, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-sm-12">
#Html.EditorFor(model => model.Inquiry, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Inquiry, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group form-group-sm col-sm-12">
<div class="row">
<div class="col-sm-12">
<div id="NotRobot">
<label>Are you Human?</label>
<div id='recaptcha' class="col-sm-12 g-recaptcha"
data-sitekey="#System.Configuration.ConfigurationManager.AppSettings["RecaptchaPublicKey"]"
>
</div>
<div id="recaptchaMessage" data-verifyrecaptchatokenurl="#Url.Action("VerifyReCaptchaToken", "Home")" style="display:none;padding:10px;color:red;font-weight:bold;" class="error">You need to verify reCAPTCHA.</div>
</div>
</div>
</div>
</div>
<div class="form-group form-group-sm col-sm-6">
<div class="row">
<div class="col-sm-9">
<input id="Send" type="submit" value="Send" class="btn btn-default" />
</div>
</div>
</div> etc...
In my controller I handle it like this thou I would like to handle the reCAPTCHA as an ajax call I have yet to figure out how to do that.
public ActionResult Index()
{
ViewData["ReCaptchaKey"] = System.Configuration.ConfigurationManager.AppSettings["RecaptchaPublicKey"];
//do something here
}
public static bool ReCaptchaPassed(string gRecaptchaResponse, string secret)
{
HttpClient httpClient = new HttpClient();
var res = httpClient.GetAsync($"https://www.google.com/recaptcha/api/siteverify?secret={secret}&response={gRecaptchaResponse}").Result;
if (res.StatusCode != HttpStatusCode.OK)
{
//logger.LogError("Error while sending request to ReCaptcha");
return false;
}
string JSONres = res.Content.ReadAsStringAsync().Result;
dynamic JSONdata = JObject.Parse(JSONres);
if (JSONdata.success != "true")
{
return false;
}
return true;
}
[HttpPost]
public ActionResult SendCustomerTeam(CustomerTeamViewModel model)
{
ContactViewModel contactModel = new ContactViewModel();
contactModel.CustomerTeamModel = model;
ViewData["ReCaptchaKey"] = System.Configuration.ConfigurationManager.AppSettings["RecaptchaPublicKey"];
if (ModelState.IsValid)
{
if (!ReCaptchaPassed(
Request.Form["g-recaptcha-response"], // that's how you get it from the Request object
System.Configuration.ConfigurationManager.AppSettings["RecaptchaPrivateKey"]
))
{
ModelState.AddModelError(string.Empty, "You failed the CAPTCHA, stupid robot. Go play some 1x1 on SFs instead.");
return View(contactModel);
}
}
My problem is the reCAPTCHA never appears on my page.
Edit:
I've tried the following simplification to see if I could find the issue.
SimplePageViewModel
public class simplePageViewModel
{
public string Name { get; set; }
}
SimplePagePartialView
#model Contact_Portal.Models.simplePageViewModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>simplePageViewModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="container">
<div class="row">
<div class="form-group form-group-sm col-sm-6">
<div class="row">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-sm-9">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group form-group-sm col-sm-12">
<div class="row">
<div class="col-sm-12">
<div id="NotRobot">
<label>Are you Human?</label>
<div id='recaptcha' class="col-sm-12 g-recaptcha" style="padding:10px;"
data-sitekey="#System.Configuration.ConfigurationManager.AppSettings["RecaptchaPublicKey"]">
</div>
<div id="recaptchaMessage" data-verifyrecaptchatokenurl="#Url.Action("VerifyReCaptchaToken", "Home")" style="display:none;padding:10px;color:red;font-weight:bold;" class="error">You need to verify reCAPTCHA.</div>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
in the controller I get the partial view shown through this line
return PartialView("View", contactModel.simplePageModel);
Still the same problem persist.
Could it be because I'm displaying my partial page containing the reCAPTCHA as part of an Jquery Ajax call ? like this:
$(document).ready(function () {
$('#subject').on("change", function (e) {
e.preventDefault();
var selectedVal = $('#subject').val();
$.ajax({
// url: "/ContactUs/GetForm",
url: '#Url.Action("GetForm", "ContactUs")',
type: "POST",
data: { searchValue: selectedVal } ,
async: true,
success: function (data) {
$('#renderForms').empty();
$('#renderForms').append(data);
},
error: function (xhr, ajaxOptions, thrownError) {
alert("An error has occured!!! " + xhr.status + " && " + xhr.responseText);
}
});
});
I've now tried a entire new project where I've simplified it all the way down to one html file:
Index.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - My ASP.NET Application</title>
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
<link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="~/Scripts/modernizr-2.6.2.js"></script>
<script src='https://www.google.com/recaptcha/api.js'></script>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
</ul>
</div>
</div>
</div>
<div class="container body-content">
<div id='recaptcha' class="col-sm-12 g-recaptcha" style="padding:10px;"
data-sitekey="#System.Configuration.ConfigurationManager.AppSettings["RecaptchaPublicKey"]"></div>
<hr />
<footer>
<p>© #DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
</body>
</html>
Still it is not visible it never appears. why is it not working ?
could it be that ASP.NET MVC is not supported by Recaptcha from google?
Your script src is wrong:
<script src='https://www.google.com/recaptcha/api.js async defer'></script>
to
<script src='https://www.google.com/recaptcha/api.js'></script>
Also could you check deveoper console, if there any error?
Well I found a solution I'm not happy with it but it works.
in my Layout file I've made a section like this:
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<script type="text/javascript">
function enableBtn() {
document.getElementById("subject").disabled = false;
}
$(document).ready(function () {
document.getElementById("subject").disabled = true;
});
</script>
Then in my view I created this
<div class="g-recaptcha" data-sitekey="*********PublicKEY*************" data-callback="enableBtn"></div>
And it seems to be working.
I wish I could make it work in the partial view because now I have to have it no matter what else will happen and not just on a submit.
I don't know if I can verify this one server side anymore as it is also outside my form. ?
Anyone with a better option would be welcomed.
EDIT:
I found a better solution for me. I changed my ajax call like this:
$('#subject').on("change", function (e) {
e.preventDefault();
var selectedVal = $('#subject').val();
$.ajax({
// url: "/ContactUs/GetForm",
url: '#Url.Action("GetForm", "ContactUs")',
type: "POST",
data: { searchValue: selectedVal } ,
async: true,
success: function (data) {
$('#renderForms').empty();
$('#renderForms').append(data);
if (!debug) {
document.getElementById("Send").disabled = true;
grecaptcha.render('Captcha', {
'sitekey': '**********PublicKey*********',
'callback': function() {
document.getElementById("Send").disabled = false;
},
'expired-callback': function() {
//document.getElementById("subject").selectedIndex = 0;
document.getElementById("Send").disabled = true;
//document.getElementById("renderForms").innerHTML = "";
}
});
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert("An error has occured!!! " + xhr.status + " && " + xhr.responseText);
}
});
});
Now it is working as I intended. At least in the user interface part.

MVC Pass value from view to dynamic partial view

I'm trying to make a partial view, which will add dynamically as much fields as I input. I input number of fields, then I want to choose days of week in formed fields and do some work with this data in controller, but I have a problem with passing amount of days in partial view.
Controller :
public class CoursesController : Controller
{
private SchoolContext db = new SchoolContext();
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "CourseId,Name,Language,LanguageProficiency,StartDate,EndDate,TeacherId,NumberOfLessonsPerWeek")] Course course)
{
if (ModelState.IsValid)
{
db.Courses.Add(course);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(course);
}
public ActionResult ShowDaysOfweek(int? countDays)
{
//countDays = 2;
ViewBag.CountDays = countDays;
var days = new List<DayOfWeek> { DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday, DayOfWeek.Saturday, DayOfWeek.Sunday };
ViewBag.DaysOfWeek = new SelectList(days);
return PartialView("ShowDaysOfweek");
}
}
In this View I can add patial view by clicking button in script:
#model SchoolManagementSystem.Models.Course
#using (Ajax.BeginForm(new AjaxOptions { }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" }
<div class="form-group">
#Html.Label("Number Of Lessons Per Week", htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-5">
#Html.TextBox("NumberOfLessonsPerWeek", null, htmlAttributes: new { #class = "form-control", #type = "number", #id = "numberOfLessonsPerWeek" })
</div>
<div>
<input type="button" value="Add days" id="Show" class="btn btn-default" />
</div>
</div>
<div id="ShowResults">
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<script type="text/javascript">
var url = '#Url.Action("ShowDaysOfweek", "Courses")';
$('#Show').on("click", function () {
var countDays = $('#numberOfLessonsPerWeek').val();
url += '/?countDays=' + countDays;
$('#ShowResults').load(url);
})
</script>
Partial view:
#for (var i = 0; i < ViewBag.CountDays; i++)
{
<div class="form-group">
#Html.Label("Day of week", htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-5">
#Html.DropDownList("DaysOfWeek", (IEnumerable<SelectListItem>)ViewBag.DaysOfWeek, htmlAttributes: new { #class = "form-control", style = "height: 35px" })
</div>
</div>
}
Is it possible to do something? Thanks!
First create the hidden field with partial view url
<input type="hidden" value="#Url.Action("ShowDaysOfweek", "Courses", new { countDays= "numberOfLessonsPerWeek" })" id="hdnURLShowDaysOfweek" />
in javascript read the url and replace the parameter
<script type="text/javascript">
var url = $('#hdnURLShowDaysOfweek').val();
$('#Show').on("click", function () {
url = url.replace("numberOfLessonsPerWeek",$('#numberOfLessonsPerWeek').val());
$('#ShowResults').load(url);
})
</script>

Binding bootstrap datetimepicker to knockoutmodel

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

Why is the submit button in my ChildForm tyring to post the main form?

This is my view it has 1 Main Form that consists of 3 child form inside.
#*MainForm*#
#using(Html.BeginForm("Create_SelectPersons","Appointment", FormMethod.Post))
{
#Html.AntiForgeryToken()
<h4>Step 2</h4>
<hr />
#Html.ValidationSummary()
#*Child Form1*#
using(Ajax.BeginForm("AddAttendeeManual", "Attendee", new AjaxOptions { HttpMethod = "POST", OnSuccess = "doneManualEmail" }))
{
#Html.HiddenFor(m=>m.SelectedManualEmail.AppointmentId)
<div class="form-group">
#Html.LabelFor(m => m.SelectedManualEmail.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-8 input-group">
#Html.TextBoxFor(m => m.SelectedManualEmail.Email, new {#class = "form-control",PlaceHolder="Email"})
//button below tries to submit entire form(main) and not the child form
<input type='submit' class="btn btn-default" value="Add>>" />
</div>
</div>
}
if (Model.IsSuperOfficeConnected)
{
#*Child Form2*#
using(Ajax.BeginForm("AddAttendeeSuperOffice","Attendee",new AjaxOptions{HttpMethod = "POST", OnSuccess = "done"}))
{
#Html.HiddenFor(m => m.SelectedSuperOfficeEmail.FirstName, new { id = "SelectedSuperOfficeEmail_FirstName" })
#Html.HiddenFor(m => m.SelectedSuperOfficeEmail.LastName, new { id = "SelectedSuperOfficeEmail_LastName" })
#Html.HiddenFor(m=>m.SelectedSuperOfficeEmail.AppointmentId)
#Html.HiddenFor(m => m.SelectedSuperOfficeEmail.SuperOfficePersonId, new { id = "SelectedSuperOfficeEmail_SuperOfficePersonId" })
<div class="form-group">
#Html.LabelFor(m => m.SelectedSuperOfficeEmail.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-8 input-group">
#Html.TextBoxFor(m => m.SelectedSuperOfficeEmail.Email, new { id = "SelectedSuperOfficeEmail", #class = "form-control", PlaceHolder = "Search in SuperOffice" })
<input type='submit' id="btnSuperOffice" class="btn btn-default" value="Add>>" />
</div>
</div>
}
}
if (Model.IsInternalAddressBookEmpty)
{
#*Child Form3*#
using(Ajax.BeginForm("AddAttendeeInternalAddressBook", "Attendee", new AjaxOptions { HttpMethod = "POST", OnSuccess = "done" }))
{
#Html.HiddenFor(m=>m.SelectedAddressBookPerson.FirstName)
#Html.HiddenFor(m=>m.SelectedAddressBookPerson.LastName)
#Html.HiddenFor(m=>m.SelectedAddressBookPerson.AppointmentId)
<div class="form-group">
#Html.LabelFor(m => m.SelectedAddressBookPerson.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-8 input-group">
#Html.TextBoxFor(m => m.SelectedAddressBookPerson.Email, new { id = "SelectedAddressBookPerson", #class = "form-control", PlaceHolder = "Search in AddressBook..." })
<input type='submit' id="btnAddressBook" class="btn btn-default" value="Add>>">
</div>
</div>
}
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input class="btn btn-default" value="<<Previous"/>
//this button which i am expecting to submit the main form, does nothing
<input type="submit" class="btn btn-default" value="Next>>" />
</div>
</div>
}
<style>
.ui-autocomplete-loading {
background: url('/Content/themes/base/images/ui-anim_basic_16x16.gif') no-repeat right center;
}
</style>
#section Scripts{
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/Scripts/jquery-ui-1.10.4.min.js")
#Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.min.js")
<script type="text/javascript">
$(function () {
$("#SelectedSuperOfficeEmail").
autocomplete({
source: '/Appointment/SuperOfficePerson',
minLength: 1,
select: function (event, ui) {
$('#SelectedSuperOfficeEmail').val(ui.item.value);
$(#Html.IdFor(m => m.SelectedSuperOfficeEmail.FirstName)).val(ui.item.FirstName);
$(#Html.IdFor(m => m.SelectedSuperOfficeEmail.LastName)).val(ui.item.LastName);
$(#Html.IdFor(m => m.SelectedSuperOfficeEmail.SuperOfficePersonId)).val(ui.item.ExternalPersonId);
}
});
$("#SelectedAddressBookPerson").autocomplete({
source: '/Appointment/AddressBookPerson',
minLength: 1,
select: function(event,ui) {
$(#Html.IdFor((m=>m.SelectedAddressBookPerson.FirstName))).val(ui.item.FirstName);
$(#Html.IdFor(m=>m.SelectedAddressBookPerson.LastName)).val(ui.item.LastName);
},
});
});
function doneManualEmail() {
$(#Html.IdFor(m => m.SelectedManualEmail.Email)).val('');
}
function done() {
$(#Html.IdFor(m=>m.SelectedSuperOfficeEmail.Email)).val('');
$(#Html.IdFor(m=>m.SelectedAddressBookPerson.Email)).val('');
$(#Html.IdFor(m=>m.SelectedManualEmail.Email)).val('');
}
</script>
}
In the above code for the Child Form1 and Child Form3, when I submit click the button next to them it submits the child form, but for the Child Form1 when i click button next to it shouldn't it be submitting the child form?
Right now it is trying to submit the mail form. Why is that?
And the Next button of type submit, for the main form does nothing when i click it.
How should I solve this issue?
Edit 1: According to answer, I could solve this problem by removing the main form and having a jquery on click function for the Next>> button. But then why does second and third child form work and not first?
It is not valid HTML. You can use multiple forms but cannot use nested forms.
From official W3C XHTML specification prohibitions
form must not contain other form elements.

Categories

Resources