Button click event not firing from javascript - c#

I need to do a postback and save the data in the screen to session when the screen is closed, for this i am using the onBeforeUnload event, and placed a hidden button in the screen. In the on before unload event I am calling the click event to call the button server event. But the event is not firing. Is anything I am missing here.
<asp:Button Style="display: none" runat="server" ID="btnHidUpdate" OnClick="btnHidUpdate_Click" />
<script type="text/javascript">
$(document).ready(function () {
window.onbeforeunload = updateSessionBeforeUnload;
});
</script>
In .js file:
function updateSessionBeforeUnload() {
var hidUpdate = $('[id$="btnHidUpdate"]')[0];
hidUpdate.click();
}
In .cs code behind:
protected void btnHidUpdate_Click(object sender, EventArgs e)
{
UpdateSession();
}

The problem is that the page loads the next page before it can execute the button click.
Use the Jquery Unload event e.g.
$(function(){
$(window).unload(function(){
// put synchronous code here to persist what you need.
});
});
You can use an Ajax event like Yuriy says however you must set async to false like this:
$.ajax({
type: "POST",
url: "Url/To/Persistance",
dataType: "json",
data : { "data" : "to be persisted"},
async: false
});
EDIT
I would avoid the click event all together and do something like this:
$(function(){
$(window).unload(function(event){
var hidUpdate = $('[id$="btnHidUpdate"]')[0];
__doPostBack(hidUpdate.attr('id'),'');
});
});
However if you must click the button try this
$(function(){
$(window).unload(function(event){
var hidUpdate = $('[id$="btnHidUpdate"]')[0];
hidUpdate.click()
alert(
"Default: " + event.isDefaultPrevented() + "\n" +
"ImedPropStopped: " + event.isImmediatePropagationStopped() + "\n" +
"PropStopped: " + event.isPropagationStopped()
);
});
});
And tell us what the alert says ?

I think the other suggestions here should work fine. I have another suggestion which you can try, and is to use GetPostBackEventReference.
You can see details about it here:
http://msdn.microsoft.com/en-us/library/aa720417(v=vs.71).aspx

You can use jquery trigger("click") function which will call the click event on the button.

In my opinion the problem is that onbeforeunload event handler intended to ask user for confirmation when he want to leave a page. And since updateSessionBeforeUnload method doesn't returns any question string, unloading process continues immediately after this method leaves.
If you can make UpdateSession method static you can call it asynchronously with async jQuery.ajax method call:
<script type="text/javascript">
window.onbeforeunload = foobar;
function foobar() {
$.ajax({
type: "POST",
url: "WebForm2.aspx/UpdateSession",
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true
});
}
</script>
[WebMethod]
public static void UpdateSession()
{
}

Related

Knockout + MVC disable html button and change color after ajax call

I want to toggle disabled property for button after ajax call is successful.
The button is doing an ajax call to backend, and if returns as success, I have to disable that specific button.
I have n buttons, because they are generated in foreach loop for a table rows.
...
<td>
<button class="button primary" data-bind="click: $parent.sendDataToApi, attr: {'disabled' : passedIntegration }, style: { background: passedIntegration ? 'gray' : '' }">Send button</button>
</td>
...
My question is, am I need to put for each button id selector, or knockout somehow "knows" which button is ajax called, and only that button to disable and change color to gray?
my knockout.js file looks like:
define(['viewmodels/shell', 'durandal/services/logger', 'plugins/dialog', 'viewmodels/shell', 'toastr', 'knockout', 'kovalidationconfig', 'plugins/router', 'typeahead.bundle'],
function (shell, logger, dialog, shell, toastr, ko, kvc, router, typeahead) {
var vm = {
activate: activate,
shell: shell,
data: ko.observableArray([]),
close: function () {
$(window).off('popstate', vm.goBack);
$(window).off('resize', adjustModalPosition);
dialog.close(vm, 'cancel');
},
goBack: function () {
$(window).off('popstate', vm.goBack);
$(window).off('resize', adjustModalPosition);
dialog.close(vm, 'back');
},
editPreregisteredChildren: function () {
router.navigate("#/function/" + this.id);
},
sendDataToApi: function () {
$.ajax({
type: "POST",
url: rootUrl + 'home/sendData',
data: ko.toJSON({
requestId: this.id
}),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
if (data.success === true) {
toastr.success(data.message)
// set that specific button disabled, remove hand-cursor, change background color to gray
} else {
toastr.error(data.message);
}
}
});
}
};
);
As you can see, I done the GET part, where on loading the rows, I setup buttons disabled/enabled, though I didnt figure it yet how to remove hand cursor on disabled button?
I stuck with other part, when I do ajax call, if call was successfull I also need to disable button.
Any suggestions how to do that?
there are a couple of ways to handle it. You didn't post which variable you are using in the forEach loop, but it will depend on that. I'm going to assume it's the "data" observableArray.
So if "data" is an array of objects, you can add an observable property to it, and then bind the disable to that property.
data = [{property: ..., disable: ko.observable()}]
Then you can pass in the array object you are on to the method by adding a parameter to the method as follows:
sendDataToApi: function (e) {
and change the binding to:
data-bind="click: $parent.sendDataToApi($data), disable: disable"
This will make "e" in the method the current iteration you are on, and then you can change set e.disable(true) when appropriate.

Ajax Request is sent more than once in a DataTable Delete action - ASP.NET, JQuery, Ajax

AJAX sent more than one request each time the function is called (ASP.NET MVC, Ajax and JQuery)
I have a webpage that has a table (using JQuery Datatable) and each row in the table has a delete button that holds the id of each row. The Id is used to send a Delete request to a Web API(in the same project) and, if the Id is correct, it will delete the row.
It works just fine if I use just once the button. However, if I click the button for one row (so it gets deleted), then, click to delete another row, I realized that the request is sent duplicated to the Web API, with both the Id of the previous call and the current call.
For that reason, the server will throw a NotFound error for the Id that had been deleted and, for the current id, it will delete just fine.
If I repeat with another button, it will send, then, three delete request.
I'm not an expert with Javascript (or ajax or jquery), so I couldn't figure out what I can do to solve it.
(I saw similar posts, but I couldn't find something that works in my case)
HTML to create each row:
// Note that it uses a data-customer-id to data attribute to hold the value
foreach (var customer in Model) {
<tr>
<td>
// ( unrelated code)
// DELETE BUTTON
<button type="button" class="btn btn-link js-delete"
data-customer-id="#customer.Id" data-toggle="tooltip"
data-placement="right" title="Using JQuery & AJAX">Delete
</button>
</td>
</tr>
}
Javascript:
<script>
$(document).ready(function() {
$("#customers").on("click", ".js-delete",function() {
//getting a reference for the button to be used when it's clicked
var button = $(this);
// call the modal (display the dialog box on the screen)
$("#deleteModal").modal();
// if the deleteConfirm button is clicked
$("#deleteConfirm").on("click", function () {
var urlLog = button.attr("data-customer-id");
$.ajax({
url: "/api/customers/" + button.attr("data-customer-id"),
method: "DELETE",
success: function () {
// case it's success, remove the row from the table
button.parents("tr").remove();
}
});
// hide de modal (dialog box)
$("#deleteModal").modal("hide");
});
});
});
</script>
Ouput in the Network tab in the browser
I was expecting that each click to a delete button would send only one request to the WebApi, not multiple requests.
That happens because you are attaching an event listener to your #deleteConfirm element every time you click on .js-delete.
Refactor and move your $("#deleteConfirm").on("click", function () ... function outside of the $("#customers").on("click", ".js-delete",function() ... block.
I modified my code following the suggestion above and separated both click functions.
Ps. If I kept both functions as they were in the beginning, one inside the other, I could use this code for the second click function it also works
$("#deleteConfirm").off().bind("click", function ()
In the end, the final script was:
$(document).ready(function() {
$("#customers").on("click", ".js-delete",function() {
//getting a reference for the button to be used when it's clicked
var button = $(this);
// STORE THE REFERENCE TO THE BUTTON
$("#deleteConfirm").data('ref', button);
// call the modal (display the dialog box on the screen)
$("#deleteModal").modal();
});
$("#deleteConfirm").on("click", function () {
//var button = $("#customers .js-delete");
// get the reference to the button
var button = $(this).data('ref');
$.ajax({
//url: "/api/customers/" + button.attr("data-customer-id"),
url: "/api/customers/" + button.attr("data-customer-id"),
method: "DELETE",
success: function () {
// case it's success, remove the row from the table
button.parents("tr").remove();
}
});
// hide de modal (dialog box)
$("#deleteModal").modal("hide");
});
});

Call asp method from c# code behind

On a web application, I need to do some conditional logic and then based on that, possibly show a dialog box. Here's what I need to do:
Button pressed, submitting two IP Addresses
Check if these addresses are 'in use'
If they are:
display confirm box
If "OK" is pressed, call C# function
Otherwise, done
If they're not:
Call C# function
When the button is pressed, it calls the clicked method btnLinkConnect_Click() in the C# codebehind. This then checks for addresses 'in use'. Stepping through with the debugger, this all works fine, but if addresses are 'in use', a javascript script is supposed to run to display the box:
<script type="text/javascript">
function askForOverride(station1, station2) {
var answer = confirm("Station(s):" + PageMethods.GetActiveStations(station1, station2) + "is/are in use. Override?");
if (answer) {
PageMethods.uponOverride(station1, station2);
}
}
</script>
But how can I get this script to run from the C# page? I've looked at ClientScript.RegisterStartupScript(), but I couldn't get it to work, and it appears not to be able to work inside the conditionals. I've looked at ajax, but I couldn't understand exactly how to call it from the C# codebehind.
What is the best way to call this script, or obtain the same result, and how should I go about it?
This may work, add some client events for button click based on condition. Please refactor if necessary
protected void btnSumbit_Click(object sender, EventArgs e)
{
//call some function to verify IP entered by user
bool isExistingIp = VerifyIp(txtIP.Text);
if (isExistingIp)
{
// event argument PASSED when user confirm to override from client side
string isoverride = Request.Form["__EVENTARGUMENT"];
if (string.IsNullOrEmpty(isoverride))
{
//register script if user hasn't confirmed yet
this.ClientScript.RegisterStartupScript(this.GetType(), "displaywarning", "displaywarning();", true);
Page.GetPostBackEventReference(btnSumbit);
}
else
{
//continue with functionality
}
}
else
{
//continue with functionality
}
}
On client side add javascript to display warning and do a post back
function displaywarning() {
var isOverride = window.confirm("do you want to override");
if (isOverride) {
__doPostBack('<%=btnSumbit.ClientID%>', 'override');
}
}
You can easily do this with jQuery AJAX calls.
ASPX
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/ui-lightness/jquery-ui.css" type="text/css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('body').on('click', '.performsMyClickAction', function () {
$.ajax({
type: "POST",
url: "BlogPost.aspx/TestIP",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
if (result.d = 1) //In use
{
$("<div>State your confirm message here.</div>").dialog({
resizable: false,
height: 210,
modal: true,
buttons: {
"Ok": function () {
__doPostBack('<%= upnl.ClientID %>', 'InUse ');
$(this).dialog("close");
},
"Cancel": function () {
$(this).dialog("close");
}
}
});
} else {
__doPostBack('<%= upnl.ClientID %>', 'NotInUse ');
}
}
});
});
});
</script>
<body>
<form id="form2" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" OnLoad="upnl_Load">
<ContentTemplate>
<div>
<asp:Button CssClass="performsMyClickAction" Text="Test IP" ID="Button3" runat="server" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
C#
protected void upnl_Load(object sender, EventArgs e)
{
string eventTarget = (this.Request["__EVENTTARGET"] == null) ? string.Empty : this.Request["__EVENTTARGET"];
if (string.IsNullOrEmpty(eventTarget)) return;
var arg = Request.Params.Get("__EVENTARGUMENT");
if (arg == null) return;
if (!string.IsNullOrEmpty(arg.ToString()))
{
if (arg.ToString().IndexOf("InUse") > -1)
{
//Call C# function for in use.
}
if (arg.ToString().IndexOf("NotInUse") > -1)
{
//Call C# function for not in use.
}
}
}
[WebMethod]
public static string TestIP()
{
//Check for IP status
if (true)
return "1";
//else
//return "0";
}
Hope this will help you.
Have a look at ClientScriptManager.RegisterStartupScript, i think this should work

jQuery Confirm Replacement In A Simple Situation [duplicate]

Following up from this question, I'm trying to implement an unobtrusive confirm dialog.
$(document).ready(function () {
$("[data-confirmPrompt]").click(function (event) {
var confirmPrompt = event.currentTarget.attributes['data-confirmPrompt'].value;
event.preventDefault();
$.prompt(confirmPrompt, {
buttons: { Yes: true, No: false },
callback: function (v, m, f) {
if (v) {
// User clicked Yes. Unbind handler to avoid
// recursion, then click the target element again
$(event.currentTarget).unbind('click');
event.currentTarget.click();
}
}
});
});
});
When the user has clicked on "Yes", I want the default action associated with the event to execute. I've done it above by unbinding the jQuery handler, and clicking the element again. This works fine when submitting a form or navigating to a different page - but of course does not work in AJAX-enabled pages, where I want to keep the jQuery event handler.
Is there an alternative generic way to execute the default action? Logically something like event.executeDefault().
Using the suggestion Alexey Lebedev made in his second comment, my current implementation now looks like the sample below, except that I've also added my own implementation of localization for the button labels.
Notes:
I'm now using a jqueryUI dialog widget
Note the use of .delegate so that the handler is "ajax-aware", i.e. works on elements added to the DOM after the page is loaded, e.g. as a result of an AJAX call
Uses a flag to prevent recursion when the user clicks Yes on the confirm dialog.
Uses jquery 1.6.4 and jquery-ui-1.8.16
If anyone can suggest improvements, please chime in.
<!-- Examples of usage -->
<input type='submit' data-confirm="OK to delete customer 123?" ... />
<a href="..." data-confirm="OK to navigate?" ... />
<!-- Implementation -->
<script type="text/javascript">
var confirmClickHandler = function (event) {
if ($(event.currentTarget).data('isConfirming')) return;
var message = event.currentTarget.attributes['data-confirm'].value;
event.preventDefault();
$('<div></div>')
.html(message)
.dialog({
title: "Confirm",
buttons: {
"Yes": function () {
$(this).dialog("close");
$(event.currentTarget).data('isConfirming', true);
event.currentTarget.click();
$(event.currentTarget).data('isConfirming', null);
},
"No": function () {
$(this).dialog("close");
}
},
modal: true,
resizable: false,
closeOnEscape: true
});
};
$(document).ready(function () {
$("body").delegate("[data-confirm]", "click", confirmClickHandler);
});
</script>
I'm doing something similar and this works fine for me:
$('#link').click(function(e){
if(!confirm('Are you sure you want to asdf?')){
e.preventDefault();
}
});
I honestly don't know if this answers your question, but it might help a bit.
Consider the following HTML:
<button onclick="alert('Hello world!');" class="btn">Test 1</button>
<button onclick="alert(this.className);" class="btn">Test 2</button>
I've added the following to my $(document).ready:
$('button').each(function() {
var btn = $(this);
var onClick = btn.attr('onclick');
//replace this with _this
onClick = onClick.replace(/this/g, "_this");
btn.attr('onclick', '');
btn.click(function() {
if (confirm('Do it?')) {
//set _this first!
var _this = btn[0];
eval(onClick);
}
});
});
It seems to get the job done. Check this jsFiddle example: http://jsfiddle.net/KeesCBakker/4jThg/.
EDIT
I've created something that looks more like your question: http://jsfiddle.net/KeesCBakker/hqLH5/. Just couldn't figure out which $.prompt plugin your were using, so I grabbed the first one I've found from github (this one only works in Chrome :S).
I was able to achieve this by calling event.stopPropagation() from a more specific context, and ensuring that I don't call event.preventDefault(). While you can't call the default action explicitly, you can set up the conditions so that the default action happens — and do as little or as much else as you wish.
// Normal event handler
$("[data-toggle]").click(ev => {
switchToTab(ev.currentTarget)
ev.preventDefault()
})
// Allow default handler in a specific case.
$("[data-toggle] ul a").click(ev => {
// Don't bubble the event to the less specific handler, above
ev.stopPropagation()
// An incorrect return value will also cancel the default action.
return true
})

jQuery rating plugin inside updatel panel

I am using a jQuery rating plugin inside a asp:listview with in a asp:update panel. Below is the function which is being called on click of rating stars.
function DisplayRatings() {
$('DIV.ratingBar').each(function() {
var id = $(this).attr('id');
var count = $(this).attr('rel');
$('#' + id).raty({
showCancel: false,
readOnly: false,
showHalf: true,
start: count,
onClick: function(score) {
// I have to pass the score and ID to server side
}
});
});
}
Now I have to pass the 'score' and 'ID' to server side and call a method which rebinds the listview and updates the rating on the screen without screen refresh.
Please suggest how to go about this.( I can't use ajax toolkit rating as it doesn't support half star rating)
To pass data to the server, just store it in hidden form fields (in the UpdatePanel):
<asp:HiddenField id="score" runat="server" name="Score" ClientIDMode="Static" />
<asp:HiddenField id="id" runat="server" name="Score" ClientIDMode="Static" />
If you had a lot of data to pass back and forth, probably it would make sense just to use one hidden field and use serialization/deserialization to store it all there. Then in your onClick function, set the values of those fields, and initiate an async postback:
$('#score').val(score);
$('#id').val(id);
__doPostBack('UpdatePanelID', '')
This will cause an async update of your UpdatePanel, same as if a bound submit control was clicked by the user.
Note that if the jQuery control itself is in the UpdatePanel, you will have to reconfigure it after the async postback, since the effect is just as if the page had been reloaded as far as it is concerned. However, any javascript code which you may have run in $(document).ready() will not run after an async postback, since the whole page wasn't actually reloaded.
Ideally, keep the rating control outside the update panel, since you probably don't want it to change as a result of an event it initiated. If this isn't possible for some reason, or you just need a dynamic way to configure it the first time it is visible, then add a hook from the end of a page refresh:
// Page startup script - this adds a hook after an update panel is refreshed
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(onRefresh);
function onRefresh(sender, args) {
// You can try to check which panel was updated
var panelsUpdated = args.get_panelsUpdated();
var panelsCreated = args.get_panelsCreated();
// but usually it's easier to just track the state of your jquery stuff
if (my_jquery_thing_is_visible &&
my_indicator_that_it_has_already_been_configured===false) {
configureJqueryThing();
}
}
Solved it by using jQuery with AJAX.
aspx
function SaveRating(id, score) {
var params = '{linkID:"' + id + '",ratingVal:"' + score + '"}';
$.ajax({
type: "POST",
url: "page.aspx/UpdateRating",
data: params,
contentType: "application/json; charset=utf-8",
dataType: "json"
});
}
aspx.cs
[System.Web.Services.WebMethod]
public static void UpdateRating(string linkID, int ratingVal)
{
//code to update to db
}

Categories

Resources