call function within a custom widget that is a callback - javascript

I'm trying to call the function SetLoginButtonLabel in widget Login from inside the function SetLoginInfo -- SetLoginInfo is a call back from the widget LogInDB. When I try to call it just using this.SetLoginButtonLabel I get error SetLoginButtonLabel is undefined. I'm also trying hitch as shown below, but thats not working either. There are several different functions I'd like to call from SetLoginInfo -- How could I use hitch or some other method to make this work?
Thanks
---Widget Login
...
postCreate: function() {
var SetLab = lang.hitch(this, "SetLoginButtonLabel");
}
Login: function() //call the database
{
LoginDB.Login("http://xxx/John Smith", this.SetLoginINfo)
},
SetLoginInfo: function(LoginData) //call back from LoginDB
{
//I've tried:
this.SetLogingButtonLabel("status"); //get an undefined error
//and
SetLab("Logout");//this just seems to get lost
},
SetLoginButtonLabel: function(status)
{
//
}
.......
---Widget LoginDB
define(['dojo/store/Memory', 'dojo/_base/xhr', "dojo/data/ObjectStore", 'dojo/_base/json'],
//functions to get data and fill data stores
function (Memory, xhr, ObjectStore) {
var TicketStore;
return {
//login
Login: function (url, callback) {
xhr.get({//send data
url: url,
handleAs: "json",
load: function (result) {
var LoginData = result;
callback(LoginData);
},
error: function (err) { }
});
}
}
});

this made it work:
LoginDB.Login(s, lang.hitch(this, this.SetLoginInfo));
All of my calls within SetLoginInfo I put a this on the front:
this.SetLoginButtonLabel("Logged In");

Related

Ajax is undefined and throws runtime exception

ajax.postJson(
"/foo/GetFoo",
{ fooName: fooName },
function (data) {
},
function (error) { });
};
My Rest api call is GetAsync()
It throws ajax is undefined : JavaScript runtime error: Unable to get property 'exceptionStart' of undefined or null reference. The custom code to make ajax call is below. The api call Getfoo is GetAsync method using attribute HttpGet. Can someone point me to the cause of this failure
var ajax = {
defaultAjaxTimeout: 600000,
exceptionStart: '<!--',
exceptionEnd: '-->',
postJson: function (url, data, success, error) {
$.ajax(
{
type: "POST",
dateType: "json",
url: url,
data: data,
timeout: ajax.defaultAjaxTimeout,
success: function (result) {
if (success) success(result);
},
error: function (jqXhr, textStatus, errorThrown) {
if (error && jqXhr) {
var responseText = jqXhr.responseText;
var index = responseText.indexOf(ajax.exceptionStart);
if (index > 0) {
var exception = responseText.substr(index + ajax.exceptionStart.length + 1);
index = exception.lastIndexOf(ajax.exceptionEnd);
if (index > 0) {
exception = exception.substr(0, index);
}
error(exception);
} else {
error(errorThrown);
}
}
}
});
},
}
The issue you're having here is that you're attempting to access the variable ajax from a closure before it's created:
var myVariable = {
myProperty: "Hello",
myFunction: function () {
//... access myVariable.myProperty -> error
}
};
There are two options here. The cleaner one, and the one I'd use is this:
var ajaxOptions = {
defaultAjaxTimeout: 600000,
exceptionStart: '<!--',
exceptionEnd: '-->'
};
var ajax = {
postJson: function (url, data, success, error) {
... ajaxOptions.exceptionStart.length
}
};
The reason this works is because ajaxOptions exists already in the scope where you declare the function ajax.postJson so it's able to reference it correctly from its closure.
The variation on this option is this:
var ajax = {
defaultAjaxTimeout: 600000,
exceptionStart: '<!--',
exceptionEnd: '-->'
};
ajax.postJson = function (url, data, success, error) {
... ajax.exceptionStart.length
};
The reason this works is because ajax is already declared, and is just attached to the closure of the function.
A second, less-clean option is to put the ajax variable as a child of the window object:
window.ajax = {
defaultAjaxTimeout: 600000,
exceptionStart: '<!--',
exceptionEnd: '-->',
postJson: function (url, data, success, error) {
... window.ajax.exceptionStart.length
}
};
The reason this works is because window always exists in all lexical scopes, so it'll have no problem referencing it. The reason it's less clean is because it pollutes the window object and any JavaScript anywhere on your page can access and change it, potentially causing unknown behavior. I'm not recommending it, I'm just providing it as an example.
The following steps helped me resolve similar problem, I used IE11
the solution to it in IE 11 can be:
under internet settings select 'Compatibility View settings',
in 'Add this website' enter server name for your website (for example: localhost ), click 'Add' btn.
Tick 'Display intranet steps in Compatibility View' box.

AJAX request returns value after function has already returned

I have a Knockout binding to my function:
<tr id="toolbarRow" data-bind="foreach: get_tabs()">
get_tabs calls load which uses an ajax request to populate the departments variable:
get_tabs = function () {
load();
return departments;
},
This causes me a problem as get_tabs returns before departments is populated by load.
Here's load:
load = function () {
$.ajax(
{
url: _spPageContextInfo.webAbsoluteUrl + "/_api/search/query?querytext='Department:*"
+ "*'&selectproperties='Department'&sourceid='B09A7990-05EA-4AF9-81EF-EDFAB16C4E31'&sortlist='Department:ascending'",
method: "GET",
headers: {
"accept": "application/xml",
},
success: onSuccess,
error: onError
}
);
},
onSuccess = function (data) {
...populating departments variable...
},
onError = function (err) {
alert("something blew up");
},
How can I keep get_tabs from returning until my ajax request finishes the onSuccess event?
As the comments point out, you can't expect to be able to return data from an AJAX request. Typically you provide a callback function that does work after the result is retrieved.
The correct way to do this when using KnockoutJS is to use an observable array. Declare a property as an observable array in your viewmodel, data-bind some HTML to it, and then populate the data when you need to. Here's a simple example:
function MyViewModel() {
this.departments = ko.observableArray([]);
this.load = function () {
$.ajax({
/* your AJAX options */
})
.success(this.departmentsLoaded.bind(this))
};
this.departmentsLoaded = function (data) {
this.departments(data);
};
}
Your view/markup would look something like this:
<div data-bind="foreach: departments">
<span data-bind="text: $data"></span>
</div>
<button data-bind="click: load">Load</button>
Example: http://jsfiddle.net/CCNtR/113/
You're getting warm. $.ajax returns immediately. What you need to do is use your success handler in the $.ajax call to react to the data that is returned by the server.
Here's what I would do:
get_tabs = function(callback) {
load(callback);
}
load = function(callback) {
$.ajax({
...,
success: function(data) {
// populate departments data
callback.apply(this, arguments);
}
});
}
Why not make departments an observable array and bind directly to that? No callback required. You'd do something like:
<tr id="toolbarRow" data-bind="foreach: departments">
function myViewModel()
{
var self = this;
self.departments = ko.observableArray();
//call the following in your document ready
myViewModel.prototype.load = function ()
{
$.ajax(
{ //make your ajax call
success: function (result,status,xhr)
{
...populating departments variable...
}
});
}
}
$(document).ready(function()
{
//Toolbar will be empty because departments is empty at this point.
ko.applyBindings(myViewModel);
//Your onSuccess handler will populate the departments observable array
//when it changes, your toolbar will populate. No need for callbacks.
myViewModel.load();
}
This is really the beauty of knockoutjs is that you don't have to worry about handling stuff like this...much ;-)
You need to return departments inside onSuccess() function
onSuccess = function (data) {
return departments;
},

Dojo Get data from server and store in a variable using xhrGet

I have the following function:
loadMsgBody: function (id) {
return dojo.xhrGet({
url: "myurl",
handleAs: "text",
content: {
id: id
},
load: function (response) {
return response;
},
error: function (response) {
alert(response);
}
});
}
And calling it:
var text = "";
this.loadMsgBody(this.msgId).then(function (response) {
text = response;
});
Now I expect to get the return value of the function but instead I am getting an empty value for text. However, in Firebug I do see the response from the server with the correct value. I've searched and found these links : DOJO xhrGet how to use returned json object?
and:
Using hitch / deferred with an xhrGet request
But I still can't get and store the data with the above code. I don't want to do the manipulation inside the xhrGet call, I want to retrieve the data and use as it will be used multiple times.
Is there anything I am missing?
Dojo's XHR methods return instances of the class dojo/Deferred, because they are asynchronous. What this means is that the functions returns before the value of the response is available. In order to work with the results of the asynchronous response you need to wait for it to return. Dojo exposes this using a uniform API, Deferreds. Instances of the dojo/Deferred class have a method then. The then method takes a function as a parameter. That function will execute once the Deferred have been resolved (in this case, when the request has completed).
var deferred = loadMsgBody();
deferred.then(function(response){
//work with response
});
I would try changing your load function to evoke your callback function:
loadMsgBody: function (id, callback) {
return dojo.xhrGet({
url: "myurl",
handleAs: "text",
content: {
id: id
},
load: function (response) {
if(callback) {
callback(response);
}
},
error: function (response) {
alert(response);
}
});
}
Try this:
loadMsgBody: function (id, callback) {
return dojo.xhrGet({
url: "myurl",
handleAs: "text",
content: {
id: id
},
load: function (response) {
callback.apply(null,[response]);
},
error: function (response) {
alert(response);
}
});
}
Then:
var text = "";
this.loadMsgBody(this.msgId, function (response) {
text = response;
console.log("text:",text); // this will show your return data
});
console.log("text:",text); // this will show empty data because ajax call is asynchrize, at this time , data not return yet.
setTimeout(function(){
console.log("text:",text); // this will show your return data again because ajax call should have finished after 30000 ms
},30000)

Extending jQuery ajax success globally

I'm trying to create a global handler that gets called before the ajax success callback. I do a lot of ajax calls with my app, and if it is an error I return a specific structure, so I need to something to run before success runs to check the response data to see if it contains an error code bit like 1/0
Sample response
{"code": "0", "message": "your code is broken"}
or
{"code": "1", "data": "return some data"}
I can't find a way to do this in jQuery out of the box, looked at prefilters, ajaxSetup and other available methods, but they don't quite pull it off, the bets I could come up with is hacking the ajax method itself a little bit:
var oFn = $.ajax;
$.ajax = function(options, a, b, c)
{
if(options.success)
{
var oFn2 = options.success;
options.success = function(response)
{
//check the response code and do some processing
ajaxPostProcess(response);
//if no error run the success function otherwise don't bother
if(response.code > 0) oFn2(response);
}
}
oFn(options, a, b, c);
};
I've been using this for a while and it works fine, but was wondering if there is a better way to do it, or something I missed in the jQuery docs.
You can build your own AJAX handler instead of using the default ajax:
var ns = {};
ns.ajax = function(options,callback){
var defaults = { //set the defaults
success: function(data){ //hijack the success handler
if(check(data)){ //checks
callback(data); //if pass, call the callback
}
}
};
$.extend(options,defaults); //merge passed options to defaults
return $.ajax(options); //send request
}
so your call, instead of $.ajax, you now use;
ns.ajax({options},function(data){
//do whatever you want with the success data
});
This solution transparently adds a custom success handler to every $.ajax() call using the duck punching technique
(function() {
var _oldAjax = $.ajax;
$.ajax = function(options) {
$.extend(options, {
success: function() {
// do your stuff
}
});
return _oldAjax(options);
};
})();
Here's a couple suggestions:
var MADE_UP_JSON_RESPONSE = {
code: 1,
message: 'my company still uses IE6'
};
function ajaxHandler(resp) {
if (resp.code == 0) ajaxSuccess(resp);
if (resp.code == 1) ajaxFail(resp);
}
function ajaxSuccess(data) {
console.log(data);
}
function ajaxFail(data) {
alert('fml...' + data.message);
}
$(function() {
//
// setup with ajaxSuccess() and call ajax as usual
//
$(document).ajaxSuccess(function() {
ajaxHandler(MADE_UP_JSON_RESPONSE);
});
$.post('/echo/json/');
// ----------------------------------------------------
// or
// ----------------------------------------------------
//
// declare the handler right in your ajax call
//
$.post('/echo/json/', function() {
ajaxHandler(MADE_UP_JSON_RESPONSE);
});
});​
Working: http://jsfiddle.net/pF5cb/3/
Here is the most basic example:
$.ajaxSetup({
success: function(data){
//default code here
}
});
Feel free to look up the documentation on $.ajaxSetup()
this is your call to ajax method
function getData(newUrl, newData, callBack) {
$.ajax({
type: 'POST',
contentType: "application/json; charset=utf-8",
url: newUrl,
data: newData,
dataType: "json",
ajaxSuccess: function () { alert('ajaxSuccess'); },
success: function (response) {
callBack(true, response);
if (callBack == null || callBack == undefined) {
callBack(false, null);
}
},
error: function () {
callBack(false, null);
}
});
}
and after that callback success or method success
$(document).ajaxStart(function () {
alert('ajax ajaxStart called');
});
$(document).ajaxSuccess(function () {
alert('ajax gvPerson ajaxSuccess called');
});

How to return a value inside AJAX function to parent in javascript?

I'm trying to return true or false to a function depending on the response of an AJAX function inside of it but I'm not sure how should I do it.
(function($) {
$('#example').ajaxForm({
beforeSubmit : function(arr, $form, options) {
var jsonStuff = JSON.stringify({ stuff: 'test' });
$.post('/echo/json/', { json: jsonStuff }, function(resp) {
if (resp.stuff !== $('#test').val()) {
// Cancel form submittion
alert('Need to type "test"');
return false; // This doesn't work
}
}, 'json');
},
success : function() {
alert('Form sent!');
}
});
})(jQuery);​
I made a fiddle to illustrate this better:
http://jsfiddle.net/vengiss/3W5qe/
I'm using jQuery and the Malsup's Ajax Form plugin but I believe this behavior is independent of the plugin, I just need to return false to the beforeSubmit function depending on the POST request so the form doesn't get submitted every time. Could anyone point me in the right direction?
Thanks in advance!
This is not possible to do when dealing with async functions. The function which calls post will return immediately while the ajax call back will return at some point in the future. It's not possible to return a future result from the present.
Instead what you need to do is pass a callback to the original function. This function will eventually be called with the result of the ajax call
var makePostCall = function(callback) {
$.post('/echo/json/', { json: jsonStuff }, function(resp) {
if (resp.stuff !== $('#test').val()) {
// Cancel form submittion
alert('Need to type "test"');
callback(false);
} else {
callback(true);
}}, 'json');
};
Then switch the code which expected a prompt response from makePostCall to using a callback instead.
// Synchronous version
if (makePostCall()) {
// True code
} else {
// false code
}
// Async version
makePostCall(function (result) {
if (result) {
// True code
} else {
// False code
}
});
you can put async:false parameter to ajax request then you can control future responce and send back the result to parent. see following main lines enclosed within ***
add: function (e, data) {
//before upload file check server has that file already uploaded
***var flag=false;***
$.ajax(
{
type: "POST",
dataType:'json',
url:"xyz.jsp",
***async:false,***
data:{
filename : upload_filename,
docname : upload_docname,
userid : upload_userid,
},
success:function(data)
{
***flag=true;***
},
error:function(request,errorType,errorMessage)
{
alert ('error - '+errorType+'with message - '+errorMessage);
}
});
***return flag;***
}

Categories

Resources