How to "bubble up" callback - javascript

In my event handler function I need to check if some field is unique. To achieve this I use ajax call to the function in back end.
From that function data is send back using callback.
at this moment I have Event handler:
self.searchKeyboardCmd = function (data, event) {
if (event.keyCode == 13) {
foo(function (callback) {
if(!callback){
return false // Returning only from this method. Not parent method
}
});
var a = new Eq();
a.StorageId(self.StorageTemp());
a.StartDate(self.StartDateTemp());
a.DeviceSerialNumber(self.Test());
a.DeviceId(self.DeviceTemp());
a.Issue(self.Issue())
a.IssueDesc(self.IssueDesc());
a.Quantity(self.number());
a.Project(self.Project());
a.MeUser(self.MeUser());
self.data.push(a);
$('.datepicker').datepicker({ autoclose: true, todayHighlight: true/*, language: "pl"*/, format: 'dd/mm/yyyy' });
self.Test("");
return false;
}
return true;
};
In which in lines:
foo(function (callback) {
alert(callback);
});
I call this method with ajax call:
function foo(callback) {
$.ajax({
url: "/DeviceInstance/IsUnique",
contentType: "application/json; charset=utf-8",
type: "POST",
datatype: "json",
data: JSON.stringify({ value: viewModel.Test() }),
error: function (data) {
alert("Dodanie nie powiodło się " + data);
},
success: function (data) {
callback(data);
}
});
}
At this moment correct data is received by foo in main method. But I need to make searchKeyboardCmd aware of the value of the callback value from Ajax call. I read in my other question that I need to make searchKeyboardCmd accepting callback from foo call.
Please do net send me to the question How do I return the response from an asynchronous call?. I'm reading that topic all day and still got nothing

What if you put all the code that depends on the callback return into the callback?
foo(function (callback) {
if(callback) { // Changed this condition
var a = new Eq();
a.StorageId(self.StorageTemp());
a.StartDate(self.StartDateTemp());
a.DeviceSerialNumber(self.Test());
a.DeviceId(self.DeviceTemp());
a.Issue(self.Issue())
a.IssueDesc(self.IssueDesc());
a.Quantity(self.number());
a.Project(self.Project());
a.MeUser(self.MeUser());
self.data.push(a);
$('.datepicker').datepicker({ autoclose: true, todayHighlight: true/*, language: "pl"*/, format: 'dd/mm/yyyy' });
self.Test("");
}
});

Just an idea - this is jQuery way. This is your function:
function foo(callback) {
return $.ajax({
url: "/DeviceInstance/IsUnique",
contentType: "application/json; charset=utf-8",
type: "POST",
datatype: "json",
data: JSON.stringify({ value: viewModel.Test() }),
error: function (data) {
alert("Dodanie nie powiodło się " + data);
},
success: function (data) {
callback(data);
}
});
}
$.ajax - returned a Defered object.
This is modified searchKeyboardCmd function:
self.searchKeyboardCmd = function (data, event) {
var dfd = $.Deferred();
if (event.keyCode == 13) {
foo(callback).done(
function() {
var a = new Eq();
a.StorageId(self.StorageTemp());
a.StartDate(self.StartDateTemp());
a.DeviceSerialNumber(self.Test());
a.DeviceId(self.DeviceTemp());
a.Issue(self.Issue())
a.IssueDesc(self.IssueDesc());
a.Quantity(self.number());
a.Project(self.Project());
a.MeUser(self.MeUser());
self.data.push(a);
$('.datepicker').datepicker({ autoclose: true, todayHighlight: true/*, language: "pl"*/, format: 'dd/mm/yyyy' });
self.Test("");
dfd.resolve();
}
);
}
dfd.reject();
};
This code is untested. When you write JavaScript you must thing asynchronously. If you provide working jsFiddle with your solution I can help you more.
Best regards.

Related

How to load data from ajax to zabuto calendar plugin?

As title, I tried load data from ajax to zabuto calendar, but seem it's not working, ref of zabuto calendar http://zabuto.com/dev/calendar/examples/show_data.html. And i want to use this function load data when click nav prev month or next month. (use two action action and action_nav). This is snipped code
<script>
$(document).ready(function () {
function load_data() {
var list = '';
$.ajax({
type: "POST",
url: "../BUS/WebService.asmx/LOAD_DATA",
contentType: "application/json; charset=utf-8",
dataType: "json",
cache: false,
success: function (data) {
list = $.parseJSON(data.d);
console.log(list);
}
});
return list;
}
function myNavFunction(id) {
//code in here
}
function myDateFunction(id) {
//code in here
}
$("#my_calendar").zabuto_calendar({
data: load_data(),
action: function () {
return myDateFunction(this.id);
},
action_nav: function () {
return myNavFunction(this.id);
}
});
});
</script>
When i test this, data not show, the data from ajax as
{ "date": "2016-06-01", "title": 2, "badge": true },{ "date": "2016-06-04", "title": 1, "badge": true },{ "date": "2016-06-10", "title": 1, "badge": true }
Thank you so much.
Try the following: you need to place the calendar function in the success function of the ajax call because ajax is asynchronous
$(document).ready(function () {
function load_data() {
$.ajax({
type: "POST",
url: "../BUS/WebService.asmx/LOAD_DATA",
contentType: "application/json; charset=utf-8",
dataType: "json",
cache: false,
success: function (data) {
var list = $.parseJSON(data.d);
$("#my_calendar").zabuto_calendar({
data: list;
});
},
error: function (data) {
console.log(data.d);
}
});
}
load_data();
});
I solved the issue by the code as below. It works well in window's browser but not in a mobile browser.
function initZabuto(id, events, month){
$('#zabuto_parent').empty().append("<div id='"+id+"'></div>");
$("#"+id).zabuto_calendar({
year:moment(month).format("YYYY"),
month:moment(month).format("MM"),
language:"cn",
data: events,
action: function () {
zabutoDayClick(this.id);
},
action_nav: function () {
zabutoMonthChange(this.id);
}
});
}
This is the code I used to refresh Zabuto calendar after a modal. The problem with other options is that upon refresh, Zabuto would create a new batch of modals appended to the current body. This solutions clears all those "old" modals and opens room for the new. Key area is the success section of the modal update ajax.
$(document).ready(function () {
$("#date-popover").popover({html: true, trigger: "manual"});
$("#date-popover").hide();
$("#date-popover").click(function (e) {
$(this).hide();
});
load_calendar();
});
function load_calendar() {
$("#my-calendar").zabuto_calendar({
show_next: 1,
action: function () {
return myDateFunction(this.id, false);
},
ajax: {
url: "calendar-info.php",
modal: true
},
});
}
function myDateFunction(id, fromModal) {
$("#date-popover").hide();
if (fromModal) {
$("#" + id + "_modal").modal("hide");
var date = $("#" + id).data("date");
var optradio = $("#" + id + "_modal").find("input[name='optradio']:checked").val();
$.ajax("calendar-update.php?status="+optradio+"&date="+date, {
success: function(data) {
$(".modal").remove();
$('body').removeClass('modal-open');
$('.modal-backdrop').remove();
$("#my-calendar").empty();
load_calendar();
},
error: function() {
alert("Problem!");
}
});
}
var hasEvent = $("#" + id).data("hasEvent");
if (hasEvent && !fromModal) {
return false;
}
return true;
}

Assigning an ajax fetch function to a variable returns undefined even though data definitely returns?

I have a data fetch function getAvailableDates that I call by assigning a variable AVAILABLE_DATES, in the done callback I log out the response and my data is there but returning the data and logging out the variable returns undefined. Can anyone explain where I might be going wrong with this?
define([
'jquery'
], function (
$
) {
"use strict";
function getAvailableDates() {
console.log('Running getAvailableDates');
var requestAvailableDates = $.ajax({
type: "GET",
url: 'api/dcgdates',
data: JSON.stringify(requestAvailableDates),
dataType: "json",
contentType: "application/json"
});
requestAvailableDates.done(function(data) {
console.log('getAvailableDates success', data);
return data;
});
}
return {
DATE_FORMAT: "dd M yy",
AVAILABLE_DATES: getAvailableDates()
};
});
Use the deferred return by the $.ajax, as you use it to log the data, its chainable, you can write:
var request = $.ajax(...);
// This will return the deferred object. And you can keep call `.done` on it to chain the callbacks.
return request.done(...).done(...);
All of the callbacks chained by .done will receive the same data from your ajax request.
define(['jquery'], function($) {
"use strict";
function getAvailableDates() {
console.log('Running getAvailableDates');
var requestAvailableDates = $.ajax({
type: "GET",
url: 'api/dcgdates',
data: JSON.stringify(requestAvailableDates),
dataType: "json",
contentType: "application/json"
});
// Return a deferred object.
return requestAvailableDates.done(function(data) {
console.log('getAvailableDates success', data);
return data;
});
}
return {
DATE_FORMAT: "dd M yy",
deferredObj: getAvailableDates()
};
});
Then you can get the object and use :
returnObj.deferredObj.done(function(data) {
// do something......
});
To get its value.
Below is a snippet to show how you can use it.
var test = function() {
var dfd = $.Deferred();
setTimeout(function() {
dfd.resolve(1);
}, 3000);
// Each .done returns the deferred object, which can be chained to more callbacks.
// And they'll execute in the order you chained them.
return dfd
.done(function(val) {
console.log(val);
})
.done(function(val) {
console.log('another ' + val);
});
};
var deferred = test();
// The return deferred object can keep chaining to get the value.
// You can write your logic here to handle the data when deferred resolved.
deferred.done(function(val) {
console.log('I got the same value: ' + val);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>

Javascript Object Initialization not working [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
Have code structure like this :
SkillEidt.js (Javascript File):
var SkillEdit = ({
_designtemplate: ["", "input", "dropdownlist", "checkbox"],
_designTemplateData: {},
readValue: function() {
/* when try to read value from customer.Html it's null */
return this._designTemplateData;;
},
RequestResponse: function (data) {
/* able to get and set value from ajax call */
this._designTemplateData = data;
},
ajaxCall : function() {
$.ajax({
url: "/VendorDetails/GetVendorDetails",
type: "POST",
async: true,
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function (result) {
alert(result.statusText);
},
success: function (result) {
requestReponse(result);
}
});
});
SkillEdit.ajaxCall() /* very important to set _designTemplateData data */
Customer.Html (page):
<script src="~/Scripts/SkillEdit.js"></script>
<script type="text/javascript">
function SomeBuuttonClickEvent() {
var notAbleToGetValue = SkillEdit.readValue();
}
</script>
------------------------------------------------------------------------
When debug and see SkillEdit.ajaxCall() will call ajaxCall() method and on success will call RequestResponse and set _designTemplateData. But When i click Button (SomeBuuttonClickEvent) on Customer.Html page readValue is returning null value. How can i set the _designTemplateData data.
..
Have added $.ajax function. How to slove the problem by using any of the solution
What code to be added
What code need to be written inside :
RequestResponse: function (data)
or
ajaxCall : function()
Please try this.
SkillEdit.js
var SkillEdit = function(){
_designtemplate= ["", "input", "dropdownlist", "checkbox"],
_designTemplateData= {},
readValue = function () {
$('#templabel').text(_designTemplateData);
return _designTemplateData;
},
RequestResponse = function (data) {
debugger;
return _designTemplateData = data;
},
ajaxCall= function () {
//return this.RequestResponse(["12", "13"]);
$.ajax({
url: "/Home/GetVendorDetails",
type: "POST",
async: true,
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function (result) {
alert(result.statusText);
},
success: function (result) {
RequestResponse(result);
console.log(result);
}
});
}
return {
readValue: readValue,
RequestResponse: RequestResponse,
ajaxCall : ajaxCall
}
}();
In ViewPage:
<script src="~/js/SkillEdit.js"></script>
<label id="templabel"></label>
<input type="button" value="stake overflow question" onclick="return SkillEdit.ajaxCall();"/>
<input type="button" value="read Value answer" onclick="return SkillEdit.readValue();" />
In Controller:
[HttpPost]
public ActionResult GetVendorDetails()
{
return Json("[12,13]");
}
Your code appears to be working : (run it below)
var SkillEdit = {
_designtemplate: ["", "input", "dropdownlist", "checkbox"],
_designTemplateData: {},
readValue: function() {
return this._designTemplateData;;
},
RequestResponse: function (data) {
this._designTemplateData = data;
},
ajaxCall : function() {
this.RequestResponse("test successful");
}
};
SkillEdit.ajaxCall()
alert(SkillEdit.readValue()) // Should alert "Test successful"
Your error may be in the treatment of your ajax response.

How to break parent function from submethod [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I have a function searchKeyboardCmd which is binded as an event handler to the textbox.
Its purpose is to check the data in that textbox is unique. If no it should break execution of this handler and show alert window. If unique it should get data from other texboxes and store it in array ( code fragment from line `var a=new ())
self.searchKeyboardCmd = function (data, event) {
if (event.keyCode == 13) { //checking if enter was pressed or other key
foo(function (result) {
if (result == 'false') {
alert("Numer seryjny nie jest unikalny");
return true;
}
});
var a = new Eq();
a.StorageId(self.StorageTemp());
a.StartDate(self.StartDateTemp());
a.DeviceSerialNumber(self.Test());
a.DeviceId(self.DeviceTemp());
a.Issue(self.Issue())
a.IssueDesc(self.IssueDesc());
a.Quantity(self.number());
a.Project(self.Project());
a.MeUser(self.MeUser());
self.data.push(a);
$('.datepicker').datepicker({ autoclose: true, todayHighlight: true/*, language: "pl"*/, format: 'dd/mm/yyyy' });
deviceIdField.focus();
self.Test("");
return false;
}
return true;
};
My foo function which call back end method. It receives as true from it if unique. False other ways.
function foo(callback) {
$.ajax({
url: "/DeviceInstance/IsUnique",
contentType: "application/json; charset=utf-8",
type: "POST",
datatype: "json",
data: JSON.stringify({ value: viewModel.Test() }),
error: function (data) {
alert("Dodanie nie powiodło się " + data);
},
success: function (data) {
callback(data);
}
});
So my problem is in breaking execution of my main event handler method.
I tried modifying this lines:
self.searchKeyboardCmd = function (data, event,callback)
and
foo(function (result) {
console.log(result);
callback(result);
});
The only response I'm getting is : undefined is not a function
Try this:
var f = foo(function (result) {
if (result == 'false') {
alert("Numer seryjny nie jest unikalny");
return true;
}
});
if(!f){
return; // (Or return true or false)
}
If f() returns false, the code below the function call won't be executed, if it returns true, it will be.

Ajax, prevent multiple request on click

I'm trying to prevent multiple requests when user click on login or register button. This is my code, but it doesn't work. Just the first time works fine, then return false..
$('#do-login').click(function(e) {
e.preventDefault();
if ( $(this).data('requestRunning') ) {
return;
}
$(this).data('requestRunning', true);
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
$(this).data('requestRunning', false);
}
});
});
Any ideas? Thanks!
The problem is here:
complete: function() {
$(this).data('requestRunning', false);
}
this no longer points to the button.
$('#do-login').click(function(e) {
var me = $(this);
e.preventDefault();
if ( me.data('requestRunning') ) {
return;
}
me.data('requestRunning', true);
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
me.data('requestRunning', false);
}
});
});
Use on() and off(), that's what they are there for :
$('#do-login').on('click', login);
function login(e) {
e.preventDefault();
var that = $(this);
that.off('click'); // remove handler
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize()
}).done(function(msg) {
// do stuff
}).always(function() {
that.on('click', login); // add handler back after ajax
});
});
In your ajax callbacks the context (this) changes from the outer function, you can set it to be the same by using the context property in $.ajax
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
context: this, //<-----
success: function(msg) {
//stuffs
},
complete: function() {
$(this).data('requestRunning', false);
}
});
You can disable the button.
$(this).prop('disabled', true);
I have also faced a similar problem.
Just adding $('#do-login').attr("disabled", true); gives me the solution.
$('#do-login').click(function(e) {
e.preventDefault();
$('#do-login').attr("disabled", true);
.........
.........
Here do-login is button id.
I've tried this and worked very fine for me, I was having trouble that $.ajax send more request until results return,
var settings = {
"url": "/php/auth/login.php",
"method": "POST",
"timeout": 0,
"async": false,
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"data": jsondata, //data pass here is in JSON format
};
$.ajax(settings).done(function (ress) {
try{
console.log(ress, "Result from Ajax here");
}
catch(error){
alert(error);
console.log(ress);
}
});
async : false worked for me.
Thanks.
Or you can do it by $(this).addClass("disabled"); to you button or link and after click is performed, you can $(this).removeClass("disabled");.
// CSS
.disabled{
cursor: not-allowed;
}
// JQUERY
$('#do-login').click(function(e) {
e.preventDefault();
$(this).addClass("disabled");
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
context: this,
success: function(msg) {
//do more here
$(this).removeClass("disabled");
},
});
});
P.S. If you use bootstrap css, you do not need the css part.
I found the approach useful. I've implemented it as a general purpose function for jQuery with ES6.
export default function (button, promise) {
const $button = $(button);
const semaphore = 'requestRunning';
if ($button.data(semaphore)) return null;
$button.data(semaphore, true);
return promise().always(() => {
$button.data(semaphore, false);
});
}
Because $.ajax() returns a promise, you simply pass in the promise and the function takes care of the rest.
Roughly speaking, here's the usage.
import preventDoubleClick from './preventdoubleclick';
...
button.click(() => {
preventDoubleClick(this, () => $.ajax()
.done(() => { console.log("success") }));
});
This function can help you with control multi Ajax requests and it's has timeout function which can return flag status to 0 after ex. 10sec (In case the server took more than 10 seconds to respond)
var Request_Controller = function(Request_Name = '', Reactivate_Timeout = 10000)
{
var a = this;
a.Start_Request = function(){
if(window.Requests == undefined){
window.Requests = {};
}
window.Requests[Request_Name] = {'Status' : 1, 'Time': + new Date()};
}
a.End_Request = function(){
if(window.Requests == undefined){
window.Requests = [];
}
window.Requests[Request_Name] = undefined;
}
a.Is_Request_Running = function(){
if(window.Requests == undefined || window.Requests[Request_Name] == undefined){
return 0;
}else{
var Time = + new Date();
// Reactivate the request flag if server take more than 10 sec to respond
if(window.Requests[Request_Name]['Time'] < (Time - Reactivate_Timeout))
{
return 0;
}else{
return 1
}
}
}
}
To use it:
var Request_Flag = new Request_Controller('Your_Request_Name');
if(!Request_Flag.Is_Request_Running()){
Request_Flag.Start_Request();
$.ajax({
type: "POST",
url: "/php/auth/login.php",
data: $("#login-form").serialize(),
success: function(msg) {
//stuffs
},
complete: function() {
Request_Flag.End_Request();
}
});
}
for prevent multiple ajax request in whole site. For example: If use ajax request in other ajax page, Using ajax in php loop, etc, Give you multiple ajax request with one result. I have solution:
Use window.onload = function() { ... }
instead of
$(document).ready(function(){ ... });
on the main index.php page. Its will be prevent all multi request. :)

Categories