How do you use, or correctly use, javascript in dynamically embedded pages/content?
When an event occurrs I am loading a PHP/HTML page into an HTML element. The javascript works fine on the outter page, or the page that the content gets loaded into, but it does not work on the page that is being loaded.
Here is my request function:
function sendServiceRequest(file, nvpSendData, successCallback, failCallback) {
$.ajax({
type: "POST",
url: file,
data: nvpSendData,
dataType: 'html'
}).success(function(data, status) {
console.log(".done");
console.log("Return AJAX status: " + status);
//console.log("success data: " + JSON.stringify(data));
successCallback(data, status);
}).fail(function(data, status, error) {
console.log(".fail");
console.log("Return AJAX status: " + status);
//console.log("Return data: " + JSON.stringify(data));
failCallback(data, status, error);
});
}
Then i have a php page, viewScripts.php, that has this javascript file included, that handles the loading process
view_events.js
document.addEventListener('DOMContentLoaded', function() {
var rx = document.querySelector("#rx-number").value;
sendServiceRequest(
"/comments/get_content.php",
{action:"loadContent", loadType:"comments", rx_number:rx},
function(data, status) {
document.querySelector("#rx-comments-container").innerHTML = data;
},
function(data, status, error) {
console.log("AJAX send service request failed while loading comments!");
}
);
});
Then in the code above, /comments/get_content.php verifies the data being sent, and then loads the page comment.php into a div element, #rx-comments-container. Up until this point everything is fine. It's the javascript in comment.php that does not want to work. I have tried including a '.js' file with the specified functions to handle events into comment.php, but this does not work. I have also tried including the event functions in view_events.js, as listed above, which is included in viewScripts.php, and this does not want to work either. I have also tried embedding the javascript directly into comments.php, but this doesn't work either.
Here is the javascript that is to be included in comments.php:
document.addEventListener('DOMContentLoaded', function() {
document.getElementsByClassName("edit-rx-comment-glyph").addEventListener("click", function () {
var id = this.value;
sendServiceRequest(
"/comments/get_content.php",
{action: "loadContent", loadType: "editComment", comment_id: id},
function (data, status) {
document.querySelector('#' + id).innerHTML = data;
},
function (data, status, error) {
console.log("AJAX send service request failed while loading edit form!");
}
);
});
document.getElementsByClassName("comment-history-glyph").addEventListener("click", function () {
var id = this.value;
sendServiceRequest(
"/comments/get_content.php",
{action: "loadContent", loadType: "viewHistory", comment_id: id},
function (data, status) {
document.querySelector('#comments-body').innerHTML = data;
},
function (data, status, error) {
console.log("AJAX send service request failed while loading edit form!");
}
);
});
});
I managed to figure this out. I guess i was doing something wrong, because my code ended up working. I just used an onclick event with the sendServiceRequest function, and that ended up working. I didn't need to include any other js files.
Related
This javascript within an Office js add-in always fails when making a get request:
function update() {
Excel.run(function (ctx) {
return ctx.sync()
.then(function () {
var company = $('#company').val();
var environment = $('#environment').val();
var apiUrl = "https://localhost:44321/api/Country";
var params = "company=" + company + "&environment=" + environment;
$.getJSON(apiUrl, params)
.done(function (result) {
showNotification(result.length);
})
.fail(function (xhr, status, error) {
//showNotification(error.statusText);
showNotification(error.length);
});
});
}).catch(function (error) {
showNotification(error);
});
}
I can see the json being returned successfully within Fiddler and JSONLint says the json is valid. Here it is:
[{"country":"UK","countryLongName":"United Kingdom","currency":"GBP"}]
I'm running on localhost with https, and have the following AppDomains in my manifest (belt and braces):
<AppDomain>https://localhost:44321/api/Country</AppDomain>
<AppDomain>https://localhost:44321</AppDomain>
<AppDomain>https://localhost</AppDomain>
However, getJSON.fail() is always invoked, with the following parameters:
xhr.responseJSON: undefined
xhr.statusText: "error"
status: "error"
error: ""
Why does getJSON always fail?
Further edit
I've tried this js instead...
$.ajax({
url: apiUrl,
dataType: 'json',
async: false,
data: params,
success: function (data) {
showNotification(data);
},
error: function (msg) {
showNotification('error : ' + msg.d);
}
});
...and now the error function is being invoked with the following parameters:
msg.responseJSON: undefined
msg.status: 0
msg.statusText: "NetworkError"
It's all to do with CORS, I found the solution in rick-strahl's post:
https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas#ApplythePolicy
Specifically,
"UseCors() has to be called before UseMvc()
Make sure you declare the CORS functionality before MVC so the middleware fires before the MVC pipeline gets control and terminates the request."
The user of my Cordova/PhoneGap app has to sign in, so I group all the form's data into a Javascript array, then I JSON.strigify() it and I send it to the server via an Ajax request.
The PHP script has been tested by manually sending the CGI command, it does perfectly works.
Also, I used alert() to check if the function sendDataToServer() is called, it is.
The problem is that Ajax doesn't output success() neither error(). AND there is no difference (exept the command, obviously) with an other working script that I use for checking a login.
Note: I use GET for testing purposes, at the end it will be POST.
Here is the WORKING script:
$("#connectionFormSubmit").click(function () {
$.ajax({
type: "POST",
url: "http://" + host + "/my_app/check_login.php",
data: "login=" + $("#login-conn").val() + "&password=" + $("#password-conn").val(),
success: function (msg) {
navigator.notification.alert(msg, alertDismissed, 'Result', 'OK');
},
error: function (jqXHR, exception) {
navigator.notification.alert(getError(jqXHR, exception), alertDismissed, 'Error', 'OK');
}
});
});
Here is the NOT WORKING script:
function sendDataToServer(dataGuest, dataChild1, dataChild2, dataChild3) {
$.ajax({
type: "GET",
url: "http://" + host + "/my_app/insert_new_user.php",
data: "guest=" + dataGuest + "&child1=" + dataChild1 + "&child2=" + dataChild2 + "&child3=" + dataChild3,
/* async: false, not changing anything */
success: function (msg) {
navigator.notification.alert(msg, alertDismissed, 'Result', 'OK');
},
error: function (jqXHR, exception) {
navigator.notification.alert(getError(jqXHR, exception), alertDismissed, 'Error', 'OK');
}
});
}
(in both cases the server script works perfectly fine).
This is how I call the function:
sendDataToServer( JSON.stringify(dataGuest), JSON.stringify(dataChild1), JSON.stringify(dataChild2), JSON.stringify(dataChild3) );
I didn't find anything simiar to my problem on Google.
I have a set of custom user data that I want to make an ajax call to, and in the event that there is no user data, make another ajax call to retrieve a default set of data, and then execute a function after parsing the data. Here's an example:
var oData = [],
exampleUrl = 'example.php';
$.ajax({
url: exampleUrl + '?query=getUserData',
contentType: 'application/json;odata=verbose',
headers: {
'accept': 'application/json;odata=verbose'
},
success : function(data, request){
// Request succeeded
// Check the results
if(data.length){
// There are custom user results!
// Parse the results
oData = data;
}
else{
// There were no custom user results...
// Run another query to retrieve default values
$.ajax({
url: examplUrl + '?query=getDefaultData',
contentType: 'application/json;odata=verbose',
headers: {
'accept': 'application/json;odata=verbose'
},
success : function(data, request){
// Request succeeded
// Check the results
if(data.length){
// There was some default data!
// Parse the results
oData = data;
}
else{
// No data was found...
// Attempt to be helpful
console.log('No Default data was found!');
}
},
error : function(data, request){
// There was an error with the request
// Attempt to be helpful
console.log('Error retrieving data:');
console.log(data);
console.log(request);
}
});
}
},
error : function(data, request){
// There was an error with the request
// Attempt to be helpful
console.log('Error retrieving Custom User data:');
console.log(data);
console.log(request);
},
complete : function(){
// Do something with the data
index.displayData(oData);
}
});
The issue is that if the second ajax call is run, oData doesn't contain any data at all when it's passed to index.displayData(). I'm guessing it has something to do with the asyncronous nature of ajax calls, but shouldn't 'complete' run after everything inside of 'success' runs?
I also know I probably shouldn't be using the ajax "Pyramid of Doom" and should be using promises, but I've tried them and keep getting the same results.
Thank you for your assistance!
As pointed out by Violent Crayon, you could try calling "complete" yourself instead of relying on JQuery's implicit control flow:
function getData(exampleUrl, onComplete){
$.ajax({
success : function(data, request){
if(data.length){
onConplete(data);
}else{
$.ajax({
success : function(data, request){
if(data.length){
onComplete(data);
}else{
console.log('No Default data was found!');
}
},
error : function(data, request){
console.log('Error retrieving data:');
}
});
}
},
error : function(data, request){
console.log('Error retrieving Custom User data:');
}
});
}
var oData = [];
getData('example.php', function(data){
oData = data;
index.displayData(oData);
}
BTW, note how you can have your async functions receive their own return and error callbacks. This can help reduce the pyramid of doom problem without needing to use promises and without needing to hardcode the return callback.
By working with promises, you can avoid the need to pass a callback into your function, and by defining a utility function you can avoid repetition of code.
//reusable utility function, which returns either a resolved or a rejected promise
function fetchData(queryString, cache) {
return $.ajax({
url: 'example.php',
data: { query: queryString },
type: 'JSON',//assumed
cache: cache,
contentType: 'application/json;odata=verbose',
headers: { 'accept': 'application/json;odata=verbose' }
}).then(function(data, textStatus, jqXHR) {
if (data && data.length) {
return data;
} else {
return $.Deferred().reject(jqXHR, 'no data returned').promise();//emulate a jQuery ajax failure
}
});
}
This allows promise methods to be used for a control structure, which :
is concise
uses chaining, not nesting
gives meaningful error messages.
//control structure
fetchData('getUserData', false).then(null, function(jqXHR, textStatus) {
console.log('Error retrieving Custom User data: ' + textStatus);
return fetchData('getDefaultData', true);
}).then(index.displayData, function(jqXHR, textStatus) {
console.log('Error retrieving default data: ' + textStatus);
});
Notes :
the null in .then(null, function(){...}) allows a successful response to drop straight through to the second .then(index.displayData, ...)
default data is cached while the user data is not. This is not necessary to make things work but will be faster next time the default data is required.
in the world of promises, this or something similar is the way to go.
I am currently developping a new website
When I am trying to create an account, I get an error like this :
Uncaught TypeError: Cannot read property 'hasError' of null.
And this is the code
function submitFunction()
{
$('#create_account_error').html('').hide();
//send the ajax request to the server
$.ajax({
type: 'POST',
url: baseUri,
async: true,
cache: false,
dataType : "json",
data: {
controller: 'authentication',
SubmitCreate: 1,
ajax: true,
email_create: $('#email_create').val(),
back: $('input[name=back]').val(),
token: token
},
success: function(jsonData)
{
if (jsonData.hasError())
{
var errors = '';
for(error in jsonData.errors)
//IE6 bug fix
if(error != 'indexOf')
errors += '<li>'+jsonData.errors[error]+'</li>';
$('#create_account_error').html('<ol>'+errors+'</ol>').show();
}
else
{
// adding a div to display a transition
$('#center_column').html('<div id="noSlide">'+$('#center_column').html()+'</div>');
$('#noSlide').fadeOut('slow', function(){
$('#noSlide').html(jsonData.page);
// update the state (when this file is called from AJAX you still need to update the state)
bindStateInputAndUpdate();
$(this).fadeIn('slow', function(){
document.location = '#account-creation';
});
});
}
},
error: function(XMLHttpRequest, textStatus, errorThrown)
{
alert("TECHNICAL ERROR: unable to load form.\n\nDetails:\nError thrown: " + XMLHttpRequest + "\n" + 'Text status: ' + textStatus);
}
});
}
It seems to be the jsonData, on the function, which is not working as well. Any idea or suggestions?
The success handler will be passed the data returned from the ajax request.
It will not have a function called hasError() because it is just a json object it will not have any functions.
The error handler should be fired if there is an http error i.e. if the ajax call returns an http 500.
I'm not familiar with prestashop, but looking over the prestashop documentation hasError is returned as a bool (not a function), so instead try (without the parenthesis).
if (jsonData.hasError)
You may also want to check if any data is returned first.
if (jsonData)
I am trying to POST some data to my ASP.Net MVC Web API controller and trying to get it back in the response. I have the following script for the post:
$('#recordUser').click(function () {
$.ajax({
type: 'POST',
url: 'api/RecordUser',
data: $("#recordUserForm").serialize(),
dataType: 'json',
success: function (useremail) {
console.log(useremail);
},
error: function (xhr, status, err) {
},
complete: function (xhr, status) {
if (status === 'error' || !xhr.responseText) {
alert("Error");
}
else {
var data = xhr.responseText;
alert(data);
//...
}
}
});
});
The problem with this script is that whenever I try to post the data, the jQuery comes back in "error" instead of "success".
I have made sure that there is no problem with my controller. I can get into my api method in debug mode whenever the request is made and can see that it is getting the data from the POST request and is returning it back. This controller is quite simple:
public class RecordUserController : ApiController
{
public RecordUserEmailDTO Post(RecordUserEmailDTO userEmail)
{
return userEmail;
}
}
I am not sure how I can get jQuery to print out any useful error messages. Currently when I try to debug the jQuery code using Chrome console it shows an empty xhr.responseText, nothing in "err" object and "status" set to "error" which as you see is not quite helpful.
One more thing that I have tried is to run the following code directly from the console:
$.ajax({
type: 'POST',
url: 'api/RecordUser',
data: {"Email":"email#address.com"},
dataType: 'json',
success: function (useremail) {
console.log(useremail);
},
error: function (xhr, status, err) {
console.log(xhr);
console.log(err);
console.log(status);
alert(err.Message);
},
complete: function (xhr, status) {
if (status === 'error' || !xhr.responseText) {
alert("Error");
}
else {
var data = xhr.responseText;
alert(data);
}
}
});
i.e. using the same script without actually clicking on the button and submitting the form. Surprisingly, this comes back with the right response and I can see my data printed out in console. For me this atleast means that my Web API controller is working fine but leaves me with no clue as to why it is not working on clicking the button or submitting the form and goes into "error" instead of "success".
I have failed to find any errors in my approach and would be glad if someone could help me in getting a response back when the form is posted.
As suggested by Alnitak, I was using complete callback along with success and error ones. Removing complete from my code fixed the issue.
Thanks to Alnitak.