Here is the layout of the page I am working on:
I am having an issue on getting the functionality working for the "Close Issue" actions. The "Save" issue performs a submit where the form data is parsed and the record is saved. If the data model fails validation, the form is reshown with the model errors, otherwise it redirects back to the index page. I want the "Close Issue" to do a submit as well. I want it to save the data (including a validation check) and then display a pop-up asking the user if they are sure they want to close the issue. I've tried numerous approaches but none are working. I can do a submit without any javascript/ajax intercept and get the form data, but can't get the modal to display. I can do the intercept of the submit, but I can't get all of the form data. I'm sure I am overlooking something. Here is the code:
The partial view I want displayed in the Modal:
#model EDAD.ViewModels.IssueViewModel
<!--Modal Body Start-->
<div class="modal-content">
<input name="IsValid" type="hidden" value="true" />
<!--Modal Header Start-->
<div class="modal-header">
<h4 class="modal-title">Close Issue</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<!--Modal Header End-->
<form asp-action="ClosetheIssue" method="post" enctype="multipart/form-data" asp-controller="Issue">
#Html.AntiForgeryToken()
<div class="modal-body form-horizontal">
<div class="form-group row">
Are you sure you want to close this issue? Once you close this issue you will no longer be able to make any changes to the issue.
</div>
<div class="form-group row">
<input id="issueid" type="hidden" asp-for="#Model.IssueData.issueId" class="form-control" value="#ViewBag.id" />
</div>
<!--Modal Footer Start-->
<div class="modal-footer">
<button data-dismiss="modal" id="cancel" class="btn btn-default" type="button">No</button>
<input type="submit" class="btn btn-success closeissue" id="btnSubmit" data-save="modal" value="Yes">
</div>
<div class="row">
</div>
</div> <!--Modal Footer End-->
</form>
</div>
<script type="text/javascript">
$(function () {
});
</script>
<!--Modal Body End-->
Here is the code for the "Close Issue" Button (and the Form action for both the "Save Issue" and "Close Issue":
<form asp-action="Edit">
<div id="closecontent">
<div id="modal-container3" class="modal fade" tabindex="-1">
<div class="modal-dialog modal-lg">
<div id="modal-content3" class="modal-content">
</div>
</div>
</div>
<input type="submit" asp-route-saveClose="close" class="btn btn-success closeissue" id="btncloseissue" data-save="modal" value="Close Test">
</div>
Here is the code for the Edit action:
public ActionResult Edit(IFormCollection collection, string saveClose)
{
if(saveClose is null || saveClose == "")
{
saveClose = "save";
}
IssueDataModel issue = new IssueDataModel();
try
{
ValidateData(collection);
if (ModelState.IsValid)
{
//Do stuff to save the data
if (saveClose == "save") {
return RedirectToAction(nameof(Index));
}
else
{
TempData.Remove("ID");
TempData["ID"] = collection["IssueData.issueId"].ToString();
TempData.Keep();
return RedirectToAction(nameof(CloseIssue));
}
}
else
{
return View(IVM);
}
Here is the CloseIssue code:
[HttpGet]
public ActionResult CloseIssue()
{
ViewBag.id = TempData["ID"].ToString();
return PartialView("_CloseIssue");
}
I've tried variations of the following (note that these don't represent the code snippets above) but can't get the form data submitted as well as showing the modal:
$('body').on('click', '.clse', function () {
var actionUrl = $(this).attr('href');
$.get(actionUrl).done(function (data) {
$('#closecontent').find('#modal-content3').html(data);
});
$(this).attr('data-target', '#modal-container3');
$(this).attr('data-toggle', 'modal');
});
$('#closecontent').on('click', '.closeissue', function (e) {
e.preventDefault();
var form = $(this).parents('.modal').find('form');
form.submit();
$('.modal').show();
})
$('#closecontent').on('click', '.relative', function (e) {
e.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var dataToSend = form.serialize();
$.post(actionUrl, dataToSend).done(function (data) {
//Some action after data is posted
});
})
$(function () {
$('#DisplayFileContent').on('click', '.fileupload', function (e) {
e.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var fdata = new FormData();
$("form input[type='text']").each(function (x, y) {
fdata.append($(y).attr("name"), $(y).val());
});
$("form input[type='hidden']").each(function (x, y) {
fdata.append($(y).attr("name"), $(y).val());
});
$.ajax({
url: actionUrl,
method: "POST",
contentType: false,
processData: false,
data: fdata
}).done((response, textStatus, xhr) => {
//Some action to show modal
});
})
});
The last one above sends some of the form's data but not all of it.
So to sum up, I need the ability to send the entire form's data on a "Close Issue" button click, and then display a confirmation dialog box once the form data is successfully saved.
Update 11/4
Let me clarify. I tried each of the different javascript options above to try and send the form data. The only one that partially worked was a modification of the last one. Here is what I have at this point on that modification:
$(function () {
$('#closecontent').on('click', '.closeissue', function (e) {
e.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = "/Issue/Edit/?saveClose=close"//form.attr('action');
var fdata = new FormData();
$("form input[type='text']").each(function (x, y) {
fdata.append($(y).attr("name"), $(y).val());
});
$("form input[type='hidden']").each(function (x, y) {
fdata.append($(y).attr("name"), $(y).val());
});
for (var pair of fdata.entries()) {
alert(pair[0] + ', ' + pair[1]);
}
alert(actionUrl);
$.ajax({
url: actionUrl,
method: "POST",
contentType: false,
processData: false,
data: fdata
}).done((response, textStatus, xhr) => {
//Do something
});
})
});
It is not setup to iterate through and determine if a checkbox is selected (It returns all of them as FALSE.
It does not iterate any of the Multi-select controls to show the selected items.
It does not iterate any dropdown controls to identify what is selected.
If I can get that working then the form data will be posted properly. I would want the multi-selects to be formatted the SAME way the FormCollection object formats them. i.e. the formcollection formats the multi-selected values like this: [Users,{L012,L013}]
I wouldn't want it to be formatted as [Users,{L012}],[Users,{L013}]
Assuming this can get worked out, the next step would be to alter what happens in the following code:
$.ajax({
url: actionUrl,
method: "POST",
contentType: false,
processData: false,
data: fdata
}).done((response, textStatus, xhr) => {
//Do something - If model didn't validate then do NOT show _Close partial view in modal
//Do Something - If model validates them display _close Partial in a modal
});
Related
have a button click in a form and have required validation when clicking on that button. I put in
if (!formHandle.valid()) { return; }
in the global site.js file where I want that event to fire first before the event for the actual button. Currently the jquery for the actual button fires first before the global jquery. How can I make sure that the global jquery fires first or is this even possible?
html
<p id="vote-status" class="card-text forum-blue">
#{if (#Model.VoteId != 0)
{
<text>
<br /Text.
<br />Text
</text>
}
else
{
<text><br />Text.</text>
}
}
</p>
#{
if (Model.AvailableVotingOptions != null)
{
#Html.DropDownListFor(m => m.VotingOptionId,
Model.AvailableVotingOptions,
"- Please select -",
new { #class = "form-control", #id = "voting-options" })
}
}
<div class="card-footer">
<div class="row">
<div class="col-sm-12 col-md-3 col-lg-3">
<button type="button"
class="btn btn-success btn-sm col-sm-12"
id="button"
data-action="submit">
<i class="fas fa-vote-yea fa-fw"></i>
#if (#Model.VoteId != 0)
{
<text>Re-Cast Vote</text>
}
else
{
<text>Vote</text>
}
</button>
</div>
</div>
</div>
Site.js (event I want to hit first)
$(document).on("click",
'[data-action="submit"]',
function (e) {
var formHandle = $(this).closest('form');
if (!formHandle.valid()) {
return;
}
if (formHandle.valid()) {
blockUI();
}
});
Document.js
$(document).on("click",
'#button',
function (e) {
e.preventDefault();
var post_url = $("#form-vote").attr("action"); //get form action url
var request_method = $("#form-vote").attr("method"); //get form GET/POST method
var form_data = $("#form-vote");
$.ajax({
url: post_url,
type: request_method,
data: form_data.serialize(),
processData: false,
async: true
}).done(function (objOperations) {
if ($("#validation-error")[0].textContent.trim() === "") {
ShowVoteStatus(true, "Your document is submitted successfully.");
}).fail(function (error) {
ShowVoteStatus(false,
"Your document was not submitted successfully.");
}).always(function (jqXHR, textStatus) {
$.unblockUI();
});;
});
https://codepen.io/bootsy1974/pen/ExggoQg
why do different functions? you can make a check before sending in the second function.
if its possible and this same one button
if its not possible to try after validation use
$("#button").trigger("click");
$(document).on("click",
'[data-action="submit"]',
function (e) {
e.preventDefault();
var formHandle = $(this).closest('form');
if (!formHandle.valid()) {
return;
}
if (formHandle.valid()) {
blockUI();
$("#button").trigger("click");
}
});
but formHandle.valid is not a function
need changed '#button' from button and created another element to binding this function. in another to try sending without validation. need do dependeces sending from validating. but you have to parallel working.
<div class="col-sm-12 col-md-3 col-lg-3">
<div id="button"></div>
<button type="button"
class="btn btn-success btn-sm col-sm-12"
data-action="submit">
<i class="fas fa-vote-yea fa-fw"></i>
#if (#Model.VoteId != 0)
{
<text>Re-Cast Vote</text>
}
else
{
<text>Vote</text>
}
</button>
</div>
and this have not '}'
$(document).on("click",
'#button',
function (e) {
e.preventDefault();
var post_url = $("#form-vote").attr("action"); //get form action url
var request_method = $("#form-vote").attr("method"); //get form GET/POST method
var form_data = $("#form-vote");
$.ajax({
url: post_url,
type: request_method,
data: form_data.serialize(),
processData: false,
async: true
}).done(function (objOperations) {
if ($("#validation-error")[0].textContent.trim() === "") {
ShowVoteStatus(true, "Your document is submitted successfully.");
}}).fail(function (error) {
ShowVoteStatus(false,
"Your document was not submitted successfully.");
}).always(function (jqXHR, textStatus) {
$.unblockUI();
});;
});
https://codepen.io/romanown/pen/QWKKERZ
deleted not worked validating
https://codepen.io/romanown/pen/zYKKKqv
I have a form that opens inside a BS4 modal window. This contents of the form comes from an AJAX request and that part works fine. However, when I submit the form (again an AJAX request) and it returns some info without closing the modal, and then I submit again, it submits twice. If I submit again, it submits 3 times, etc etc, each time one more submit.
What I missing here? This is my code:
<div id="empModal">
... modal stuff here ...
<div id="NewCustomer" class="col-12 view">
<div id="NewCustomerErrors"></div>
<form name="create_account" class="needs-validation" novalidate>
<div class="form-group">
... form stuff here ...
</div>
<div class="pull-right mt-3">Add new customer</div>
<div class="pull-left mt-3">Back to Log In</div>
</form>
</div>
... modal stuff here ...
</div>
Part 1
$(document).ready(function () {
$("#empModal").on('click', '#customerNewSubmit', function(e) {
$('.needs-validation').on('submit', function(e) {
if (!this.checkValidity()) {
e.preventDefault();
e.stopPropagation();
}
e.preventDefault();
e.stopPropagation();
$(this).addClass('was-validated');
var values = $(this).serialize();
doCreateAccount(values);
});
$('.needs-validation').submit();
return false;
});
});
Part 2
function doCreateAccount(values) {
$.ajax({
url: 'ajax_controller.php',
type: 'post',
dataType: 'json',
data: values+'&act=new',
success: function (res) {
if (res.result_success == true) {
$("#userButton").html(res.result_content);
$('#empModal').modal('hide');
} else {
$("#addNewCustomerErrors").html(res.result_content);
}
},
});
}
from your part 1.
$('.needs-validation').submit();
Comment this code because this is submitting a form again after single submission.
I am trying to have a modal window popup listing off any validation errors to the user when they submit the form. With my current code, the window is opening as a completely new view instead of a modal window. How can I get this window to overlap the form's view instead of opening an entirely new view?
Controller
[HttpPost]
public IActionResult Daily(Daily dailyReport)
{
var dr = new ReportDaily();
var rc = new ReportDailyCriteria();
dr.Preview(rc, IntPtr.Zero, out Notification notification);
if (notification.HasErrors) {
var error = new Errors();
string errorString = notification.GetConcatenatedErrorMessage(Environment.NewLine + Environment.NewLine);
error.ErrorList = errorString;
return PartialView("_ErrorsModal", error);
}
return View(dailyReport);
}
Partial View
#model Test.Areas.Reports.Models.Errors
<!-- Modal -->
<div id="errorsModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title float-left">Error List</h4>
<button type="button" class="close" data-dismiss="modal"></button>
</div>
<div class="modal-body">
<label>Errors: #Model.ErrorList</label>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
</div>
</div>
</div>
</div>
As far as I understand you are posting your form to controller action as full post back. Instead, you need to send it as ajax post, this will give you flexibility working with the response.
I would recommend to render your modal on the initial page load and then working only with JSON when receiving result from controller. It will eliminate complex parsing logic of response (figuring out if it is a partial view or something else for proper further action).
So render your partial view on the main view (remove Errors: #Model.ErrorList from partial view and leave label empty as you don't need that anymore):
#Html.Partial("_ErrorsModal")
Your controller action that will return Json:
[HttpPost]
public IActionResult Daily(Daily dailyReport)
{
var dr = new ReportDaily();
var rc = new ReportDailyCriteria();
dr.Preview(rc, IntPtr.Zero, out Notification notification);
if (notification.HasErrors)
{
return Json(new
{
success = false,
message = notification.GetConcatenatedErrorMessage(Environment.NewLine + Environment.NewLine)
});
}
return Json(new { success = true });
}
And your ajax call when you post the form:
$.ajax({
type: 'POST',
data: JSON.stringify($('#your_form_id').serializeArray().reduce(function(m,o){ m[o.name] = o.value; return m;}, {})),
url: 'http://your_website/your_controller/Daily',
contentType: 'application/json; charset=utf-8',
success: function (data) {
if(data.success){
//your actions when validation successful...
} else {
$('#errorsModal .modal-body label').html(data.message);
$('#errorsModal').modal('toggle');
}
}
});
I have a bootstrap modal popup, with an ajax helper form on which I need to do some js validation prior to submitting. If validation fails, I'm showing some extra things on the form. If my validation passes I want to submit the form, and update a specific div with a PartialView. To do the validation, I'm calling a js function from a button on the form, and passing in the form. If my validation passes, I call the form's submit.
This works, but the PartialView displays full page, rather than in the target div. The form works properly and updates the target div when I submit directly from a submit input on the form instead of submitting from the js function.
How do I update my target div when submitting from js function?
See code:
function validateActionItem(sender) {
var $formToSubmit = $(sender).closest('form');
$formToSubmit.submit();
}
<div id="MyDivContainer" class="col-lg-12">
#Html.Action("MyPartial", "MyController", new { ID = Model.ID })
<div class="modal fade" id="MyModal">
<div class="modal-dialog modal-lg">
<div class="modal-content">
#using (Ajax.BeginForm("MyAction", "MyController",
new { ID = Model.ID },
new AjaxOptions {
UpdateTargetId = "MyDivContainer",
OnSuccess = "closeModal()"
},
new { #id = "MyForm"}))
{
<div class="modal-body">
<!-- My form fields -->
</div>
<div class="modal-footer">
<button class="btn btn-primary" role="button"
type="button" onclick="validate($(this))">
Validate Submit
</button>
</div>
}
</div>
</div>
</div>
My _Layout.cshtml contains...
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
The MyAction action returns PartialView(model).
Can anyone point to what I'm doing wrong, and why my PartialView displays full page when submitting the form from javascript but properly updates the target div when I replace the button with a regular input submit on the form?
UPDATE
I have refactored the submit like so, but it's never getting called for some reason?
jQuery().ready(function () {
$("#MyForm").submit(function (e) {
$.ajax({
url: "/MyController/MyAction",
type: "POST",
dataType: "html",
contentType: false,
data: $("#MyForm").serialize(),
success: function (partialViewResult) {
closeModal();
$("#MyDivContainer").empty().append(partialViewResult);
}
});
});
});
UPDATE 2
I discovered that the jquery script must be after the modal popup in my cshtml, so now I'm reaching the submit event of my input button. However, I can't get to my controller action... the ajax call errors.
$("#MyForm").submit(function (e) {
e.preventDefault();
var id = $('#ID').val();
alert("submit function called");
alert("ID: " + id);
$.ajax({
url: "/MyController/MyAction",
type: "POST",
dataType: "html",
data: { ID: (id)},
error: alert("Error!")
});
});
I hit the "Error" alert, and don't know how to debug this to figure out what's wrong.
I've got it working. Thanks everyone for the help. Here's the code:
For whatever reason, the script has to be placed after the modal popup markup.
<script type="text/javascript">
$("#MyForm").submit(function (e) {
e.preventDefault();
//getting fields to be checked
if //checking failed validations
{
//doing some things if val fails
}
else
{
var id = $('#ID').val();
$.ajax({
url: "/MyController/MyAction",
type: "POST",
dataType: "html",
data: {ID: id},
success: function (partialViewResult) {
closeMyModal();
$("#MyDivContainer").empty().append(partialViewResult);
}
});
}
});
</script>
We are building a register page which is a django populated form with two empty boxes to enter/confirm password. This form is then intercepted when submit is clicked and an Ajax call is performed. But in some cases the browser(Chrome)is making a get call with the form data and also making the API call. This is obviously dangerous because the password will be visible in plain text in the URL. e.preventDefault is also not preventing this GET call. Here is my current code:
<form class="form-signin" id="provisionForm" name="provisionForm" ng-submit="submit()">
<h2 class="form-signin-heading">Register</h2> {% csrf_token %}
{{ form.as_p }}
<div class="registrationFormAlert" id="divCheckPasswordMatch"></div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Register</button>
</form>
<script src="//code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js">
<script>
$(document).ready(function(){
$("#id_confirm_password").keyup(function() {
var password = $("#id_password").val();
$("#divCheckPasswordMatch").html(password == $(this).val() ? "" : "Passwords do not match!");
});
$("#id_password,#id_confirm_password").tooltip();
var options = {};
options.ui = {
bootstrap2: false,
showErrors: false,
showVerdicts: true,
};
$("#provisionForm").submit(function(e)
{
e.preventDefault();
var frm = $('#provisionForm');
var url = '/register/'
$('#id_first_name').removeAttr('disabled');
$('#id_email').removeAttr('disabled');
$('#id_last_name').removeAttr('disabled');
$('#id_tenant_name').removeAttr('disabled');
$.ajax({
type: 'POST',
url: url,
data: frm.serialize(),
processData:false,
success: function (data) {
/*if (signup)
alert('Thank you for completing the registration process. Our support team will be in touch via email to inform you when your account is ready for use.');*/
window.location.href = data.href;
},
error: function(data) {
if (data.status == 491){
var obj = JSON.parse(data.responseText);
alert(obj.msg);
}else{
$('#regDiv').html(data.responseText);
}
}
});
$('#id_first_name').attr('disabled','disabled');
$('#id_email').attr('disabled','disabled');
$('#id_last_name').attr('disabled','disabled');
$('#id_tenant_name').attr('disabled','disabled');
return false;
})
});
</script>
</body>
</html>
How do I stop this from happening?