jQuery modal dialog first open works, subsequent opens fail - c#

I've got an MVC project written in C# using Razor Engine. I'm calling a modal through jQuery which loads a form to POST fields to my controller via AJAX, returning updated content that loads into the calling DIV.
This works wonderfully ... once. Attempting to open the modal again (to edit a different row), the form loads into the browser as if redirected, rather than displaying it in a modal dialog.
In my view, I'm calling my modal from a link (Custom HTML Helper, line breaks added only for readability):
#Html.NoEncodeActionLink("<span class='glyphicon glyphicon-pencil'></span>", "Edit Phone", "Edit", "PhoneLinks",
theseRouteValues: new { id = item.id },
theseHtmlAttributes: new {
data_modal = "",
data_toggle = "modal",
data_dismiss = "modal",
data_title = "Edit Phone",
data_btnlabel = "Edit Phone",
data_callingdiv = "replaceTargetPhone",
data_whichform = "PhoneLinkModalForm",
#class = "btn btn-primary btn-xs"
}
)
Clicks on the link are caught in my jQuery and handled there with AJAX.
jQuery(function () {
jQuery.ajaxSetup({ cache: false });
// Initialize the modal DIV
var $modalDiv = jQuery("<div class='modalContent'></div>")
.appendTo('body')
.dialog({
modal: true,
autoOpen: false,
position: { my: 'center', at: 'center', collision: 'fit' },
show: { effect: 'blind', duration: 300 },
hide: { effect: 'explode', duration: 500 },
close: function () { jQuery('div.modalContent').empty(); }
});
// Create a modal popup when a modal-generating link is clicked
jQuery("a[data-modal]").on("click", function (e) {
e.preventDefault();
// Gather parameters from the link into variables for readability
var sourceLink = jQuery(this);
var sourceHref = sourceLink.attr('href'); // Relative path to controller method
var titleData = sourceLink.data('title'); // Title for the modal dialog
var callingDiv = "#" + sourceLink.data('callingdiv'); // #replaceTarget divs ... where to apply refresh after AJAX returns
var whichForm = "#" + sourceLink.data('whichform'); // ID of the form called by the link that will be submitted in the modal
var btnProceed = sourceLink.data('btnlabel'); // Which function was called: Create/Edit/Delete (for button labelling)
var btnCancel = "Cancel";
var theseButtons = {};
// Submit Button
theseButtons[btnProceed] = function () {
// Send parameters to another function for processing
// On success, the processForm() function closes the modal
processForm(theModalContent, callingDiv, theModalContainer, sourceHref, whichForm, titleData);
};
// Cancel Button
theseButtons[btnCancel] = function () {
jQuery('div.modalContent').empty().dialog('close');
return false;
};
// Add a few parameters to the modal (title, buttons, etc.) and load content
$modalDiv.empty();
$modalDiv
.load(sourceHref)
.dialog({
title: titleData,
buttons: theseButtons
});
$modalDiv.dialog('open');
});
});
The processForm() function handles the AJAX call to the controller, and it works as expected. On success, it closes the modal with the same line of code in the Cancel button:
jQuery('div.modalContent').empty().dialog('close');
I can open the modal the first time without issue.
First call to modal works perfectly.
I can cancel the modal and reopen it as many times as I want.
If I submit the form in the modal, the form is processed correctly, my database updates correctly, and the content reloads in the target DIV correctly. However, if I then try to open a subsequent modal (for editing another phone number), the form doesn't load into a modal. It instead loads as the body of a new HTML document.
Second call to modal fails.
I have tried closing the modal in many different ways:
.dialog('destroy')
or
.remove()
or
.dialog('destroy').remove()
I have also tried initializing the modal within the "a[data-modal].on('click') function, rather than initializing on document ready.
All working variations work the first time, then fail after the first submit.
Any suggestions are greatly appreciated!
UPDATE: Added processForm() function code.
function processForm(thisModalContent, thisCallingDiv, thisModalContainer, thisMethod, thisForm, thisTitle) {
// Capture the form fields
var formPost = jQuery(thisForm);
// Serialize the fields to an array
// This step is necessary to handle phone number mask removal
var values = formPost.serializeArray();
// Some code here removes phone masking and
// puts the raw numbers back into the array
// Convert the serialized array to a single string for POST
var serializedPost = jQuery.param(values);
// Send data to controller and handle response
jQuery.ajax({
url: thisMethod,
type: 'POST',
data: serializedPost,
error: function (x, e) {
if (x.status === 0) {
alert('You are offline!!\n Please Check Your Network.');
} else if (x.status === 404) {
alert('Requested URL not found.');
} else if (x.status === 500) {
alert('Internal Server Error.\n DataSent: \n' + serializedPost + '\n Response Text: \n' + x.responseText);
} else if (e === 'parsererror') {
alert('Error.\nParsing JSON Request failed.\n' + x.responseJSON);
} else if (e === 'timeout') {
alert('Request Time out.');
} else {
alert('Unknown Error.\n' + x.responseText);
}
},
success: function (result) {
if (result.success) {
//jQuery('div.modalContent').dialog('destroy').remove(); // Didn't Work
//jQuery('div.modalContent').dialog('destroy'); // Didn't Work
//jQuery('div.modalContent').remove(); // Didn't Work
jQuery('div.modalContent').empty().dialog('close');
jQuery(thisCallingDiv).load(result.url);
} else {
thisModalContent.html(result);
}
}
});
return false;
}
Also, it's worth mentioning that while the code in this example is referencing phone numbers, I have a DIV for addresses on the same page. The Address editing link click calls the same jQuery modal.
If I submit a phone edit, subsequent calls to the modal from phone edit links are broken.
BUT I can successfully call the address edit modal ... once. Then subsequent calls to it are broken.
Refreshing the page fixes the modal from both link types (phones and addresses). Both types can be opened and cancelled repeatedly until one is submitted. Then that one is broken, but the other still works until it is submitted.

Related

Why does my function stop working without an alert?

So I've got this function right here in my view:
function izbrisi() {
var b = document.getElementById('proizvod').value;
{
$.ajax({
url: '#Url.Action("IzbrisiProizvod", "Proizvod")',
data: { id: b }
}).done(function () {
alert('Izbrisan');
});
alert('Izbrisan'); #* bez ovoga se ne brise proizvod *#
}
}
The controller it's passed to:
public ActionResult izbrisiProizvod(int Id)
{
RadniProizvod.IzbrisiProizvod(Id);
return View();
}
And finally the "IzbrisiProizvod" method:
public void IzbrisiProizvod(int IdProizvoda)
{
Proizvod izbrisaniProizvod = azilEntities.Proizvods.FirstOrDefault(x => x.idProizvoda == IdProizvoda);
azilEntities.Proizvods.Remove(izbrisaniProizvod);
azilEntities.SaveChanges();
}
For whatever reason, if I don't add the final alert (the one where there's a comment), the code just will not work. Nothing gets deleted, nothing gets reported to the console. As soon as I add in the final alert, it will magically start working.
Can someone explain this magic to me?
Always write your jquery functions like this, as per documentation. (The always is optional)
// Assign handlers immediately after making the request,
// and remember the jqXHR object for this request
var jqxhr = $.ajax( "example.php" )
.done(function() {
alert( "success" );
})
.fail(function(jqXHR, textStatus, errorThrown) {
alert( "error" );
})
.always(function() {
alert( "complete" );
});
So in your case:
function izbrisi() {
var b = document.getElementById('proizvod').value;
{
$.ajax({
url: '#Url.Action("IzbrisiProizvod", "Proizvod")',
data: { id: b }
}).done(function () {
alert('Izbrisan');
}).fail(function() {
alert( "error" );
}).always(function() {
alert( "complete" );
});
}
}
And maybe change alerts to console log or similar.
Try Network tool within your browser dev tools. For example for Firefox Dev Tools. When you click your element (let's say button) you should see new http request in the list of all request within Network tool. If you don't then your ajax call didn't happen at all or it was happen on previous page because you've experienced page reloading. Check if Proizvod actually deleted. If it is then your js function works but you don't see response. If there is s new http request within Network tool, inspect it a little bit to see what is happen (just click on it and in the right you will see details).
Also, you can open console and instead click the html element type in your console: izbrisi(). Function should execute and if it works you will see a new http request in Network tool and your alert for done will popup. If this is the case then your html element has default behavior on click event. So you should prevent it in order to prevent page reloading. Let say that you use a button for click on it. The button html should look like:
<button onclick="izbrisi(e)">Izbrisi</button>
And the js function:
function izbrisi(e) {
e.preventDefault();
// ... your code goes here
}
For whatever reason, if I don't add the final alert (the one where there's a comment), the code just will not work. Nothing gets deleted, nothing gets reported to the console. As soon as I add in the final alert, it will magically start working.
Your ajax only contains the .done() promise callback. This will only execute if the ajax request receives a 200 success code. You can add in the .fail() promise to with a unique alert to see what is happening.
In your code, the final alert is fired no matter what.
Try this to help see what is going on. Use this fiddle and open your console also. Note the different alert messages in the .done() and .fail() promises.
//var b = document.getElementById('proizvod')?.value;
$.ajax({
url: '#Url.Action("IzbrisiProizvod", "Proizvod")',
data: {
id: 'someData'
}
}).done(function() {
alert('success');
}).fail(function() {
alert('error');
});
console.log('i fire no matter what');

MVC ActionLink calling multiple JQuery functions

I'm trying to call a confirm, then an alert function from an MVC action link and I'm stuck. The code is as follows:
My view has the following actionlink:
#Html.ActionLink("JQuery Testing", "BuildProject", Model, new { onclick = " return ConfirmProjectSubmit()" })
which calls the controller to save a project to the database. I'm trying to throw a confirm statement onClick. Once that action is performed, the following action is called:
return RedirectToAction("ProjectDetails", "Project", new RouteValueDictionary(new { id = currentProject.Id, msg = message }));
to alert the user that the project was actually created.
and then at the bottom of my view:
#section scripts {
<script type="text/javascript">
function ConfirmWorkflowSubmit() {
$.confirm({
title: 'Confirm!',
content: 'Simple confirm!',
buttons: {
confirm: function () {
},
cancel: function () {
}
}
});
return false;
};
</script>
#if (ViewBag.message != null)
{
<script type="text/javascript">
$(document).ready(function () {
$.alert({
title: 'Workflow successfully created',
content: '#ViewBag.message',
type: 'green',
});
});
</script>
}
}
both of the actions are firing, but incorrectly. I'm newer to MVC and moreso to Jquery. Basically I need to figure out how to not have it submit if the user doesn't confirm, and then make sure the message only pops on the way back. I think I just need help ordering what I have properly.
Thanks in advance.
EDIT. Okay, so I see part of the problem. It's not the $confirm function that's actually submitting the form, it's the button action clicked once the dialog is open. I'm really stuck here, and this has to be easier than I'm making it. Help!
I'm not saying you can't do it the way you have, but this is normally how I set up my bindings:
$(document).ready(function ()
{
// add the e here -- it is the event which initiated the binding
$(".buildButton").on("click", function (e)
{
if (ConfirmProjectSubmit())
{
alert('confirm');
}
else
{
// e.preventDefault() cancels the click action
e.preventDefault();
alert('cancel');
}
});
});
function ConfirmProjectSubmit()
{
// some confirm logic
// return true for confirmed, false for cancelled
return false;
}
Remove the onclick in your action. There is no need to have a jQuery binding and an onClick.
This is sort of an outline, you can add your logic in various places to finish it out.

Show confirm dialog from code behind ASP.NET

I want to show confirm dialog from code be hind.
I have a comfirm dialog A. when I click button OK on A, it was call to the method B in code be hind(using ajax post: url/B and B is a method has webmethod attribute).
In method B I want to show other dialog, and code is flowing:(B is AlertInformLogOut )
[WebMethod]
public static void AlertInformLogOut(string alertId, string option)
{
//TODO: Open call schedule
var page = HttpContext.Current.Handler as Page;
// PopUp alert notify info
if (page != null)
{
page.ClientScript.RegisterStartupScript(page.GetType(), "script", "AlertSetDialog(" + new JavaScriptSerializer().Serialize(new AlertInformEntity()) + ", 'AlertInforms');", true);
//ScriptManager.RegisterClientScriptBlock(page, page.GetType(), "script", "AlertSetDialog(" + new JavaScriptSerializer().Serialize(new AlertInformEntity()) + ", 'AlertInforms');", true);
}
}
problem is: Dialog not showing.
Can some body tell me why, and can I showing dialog from a method has webmethod attribute.
The problem is, as I recall, a WebMethod wont update the page, unlike an ASP:update panel call back.
As you are using jQueries ajax function, use the success call back there, instead of trying to do it server side.
$.ajax({
type: "POST",
url: url+"/UpdateAlertInfo",....,
success: /*Call you Confirm Function Here */
}
You may alss want to consider using $.post() insteado

mvc form collection issue

I am facing a weird problem. I have a cshtml form:
<label class="pre_req_questions_width">
#Html.RadioButton("radioGroup" + Model.ID, "1", (Model.ExpectedResponse == 1 ? true : false), new { id = "rbtnYes", style = "margin-top:0px; margin-right:10px;" })Yes</label>
<label class="pre_req_questions_width">
#Html.RadioButton("radioGroup" + Model.ID, "2", !(Model.ExpectedResponse == 1 ? true : false), new { id = "rbtnNo", style = "margin-top:0px;margin-right:10px;" })No</label>
On form submit, I am getting radio group value like this:
int radioValue = int.Parse(fc.GetValue(controlID).AttemptedValue);
It works fine when i call it from #Html.BeginForm(), but when i try to send form collection via ajax like this:
input = $(':input')
$.ajax({
type: "POST",
url: '#Url.Action("SavePrerequisiteQuestion", "Dashboard", new { id = #Model.ID })',
data: input,
dataType: "html",
success: function (msg) {
alert("fine");
}, error: function (req, status, error) {
// with error
alert(error);
}
});
It send both values like this "1,2" rather than sending just selected/submitted value.
In your ajax request, you're sending all :input elements as your data:
...
data: input
...
What you probably want is to just serialize your form data, and send it with the request:
...
data: input.closest('form').serialize()
...
This is assuming you have your radio buttons in a <form> tag.
It may not be so easy to work around this. For instance, to get a selected radio button, you can do this: jQuery get value of selected radio button
So you can't just take all inputs and get the values from them... instead, you have to have more of a selective approach, and handle different elements appropriately. Checkboxes and selects will also have a similar problem.
You can put the #Html.Beginform back in and hijack the form submit in your jQuery
$('#formID').on('submit', function(e){
e.preventDefault(); // Just to stop the automatic Non Ajax submission of the form
$.post($(this).attr('action'), $(this).serialize(), function (data) {
//do stuff on success callback
alert("fine");
});
});
You can inherit the action path from the Html.BeginForm itself in the path below by doing
$(this).attr('action')
Note: If you want to manually put the path in there you still can instead of getting it
from the form
Then use $(this).serialize() to just serialize the whole form like the person above me
suggested

process to mvc action after jquery confirmation button is clicked

I'm trying to implement jquery onclick confirmation dialog to my mvc3 delete actions.
Worth to mention is that I'm succ. render dialog itself, where I'm struggle is process action to /User/Delete action from js after the continue button is clicked. Here's the code:
onclick-delete.js
$(function () {
var deleteLinkObj;
// delete Link
$('.delete').click(function () {
deleteLinkObj = $(this); //for future use
$('#delete-dialog').dialog('open');
return false; // prevents the default behaviour
});
//definition of the delete dialog.
$('#delete-dialog').dialog({
autoOpen: false, width: 400, resizable: false, modal: true, //Dialog options
buttons: {
"Continue": function () {
$.post(deleteLinkObj[0].href, function (data) { //Post to action
// THIS IS WHERE I SHOULD SEND DATA TO MY DELETE ACTION (Users/Delete)
else {
alert("error");
}
});
$(this).dialog("close");
},
"Cancel": function () {
$(this).dialog("close");
}
}
});
});
So, what I'm doing wrong.
After clicking error is thrown, any ideas
Correct me if I wrong, but isn't this way simpler and more effective
#Html.ActionLink("Delete", "Delete",
new { id = item.Id },
new { onclick = "return confirm('Are you sure you wish to delete this article?');" })
As per the discussion in Mark Oreta's answer, here's what I would do:
If you set up the form like always, you can still get confirmation from the user without too much hassle. Take the following HTML/JS:
<form action="/User/Delete" method="post">
<!-- some fields here -->
<input id="btnSubmit" type="submit" value="Delete" />
</form>
This should properly submit the form to the backend. Interesting to note is that if you click the submit button, any click event set up in javascript/jQuery will be executed before submitting the form.
So you can do:
$("#btnSubmit").click(function(event) {
event.preventDefault(); // --> This stops the form submit from happening.
});
If all you need is a textbox in which the user confirms, there is no need to use anything other than the standard confirm() function. This messages the user and asks him to either agree or cancel. The function returns true/false according to the user's response.
So you can write the simplest of code:
$("#btnSubmit").click(function(event) {
var confirmationmessage = "Are you sure you want to delete this?";
if( ! confirm(confirmationmessage) ) {
// !confirm == the user did not confirm. Therefore stop the form submission.
event.preventDefault(); // --> This stops the form submit from happening.
} else {
// The user agreed. There is no else block needed, then normal form submission may occur.
}
});
This code is much simpler and easier to read than the snippet in your question. Of course, if you prefer using any other means of asking confirmation from the user, that works too. Just make sure you end up with an if(someboolean) { event.preventDefault(); } at the end of it.
I've created a JSfiddle for you here
I'm hoping you pulled out some relevant code, because your post function was setup incorrectly. I got it working like this:
$(function () {
var deleteLinkObj;
// delete Link
$('.delete').click(function () {
deleteLinkObj = $(this); //for future use
$('#delete-dialog').dialog('open');
return false; // prevents the default behaviour
});
//definition of the delete dialog.
$('#delete-dialog').dialog({
autoOpen: false, width: 400, resizable: false, modal: true, //Dialog options
buttons: {
"Continue": function () {
$.post(deleteLinkObj[0].href, function (data) {
//do the data parsing here
alert(data);
});
$(this).dialog("close");
},
"Cancel": function () {
$(this).dialog("close");
}
}
});
});​
Where you see do the data parsing here is where you need to handle what your controller is returning. Normally, when I do something like this, my return from the delete action on the controller is a boolean value, so that in the Jquery above, you could do something like
if (data == true)
alert("success!");
else
alert("error");
Try this:
<script type="text/javascript">
$(document).ready(function () {
$('form[action$="/Delete"]').submit(function () {
return confirm('Are you sure you want to delete ?');
});
});
</script>
Think that's about all, using jQuery events.. http://api.jquery.com/submit/

Categories