I am currently creating a feature on a webpage that aims to create an HTTP request to a server with js when a certain dropdown menu value is changed and the change the webpage based on the request response.
To accomplish this, I am using a Laravel #include to include the view that will build the page based on the json response.
The problem lies on this line allNews.innerHTML+=(`#include('partials.news.post',['news'=>`+news.data[i]+`])`)
The problem here is that an error (in the view caused by the argument news.data[i] being null) is immediately thrown by js when the page is loaded, it doesn't even wait for the EventListener to be triggered or for the request to be answered. If I delete this line of code it does not throw any error and works as expected, but if I comment it, the same error happens, which seems odd to say the least. What seems to be the problem here?
I used this stackoverflow question to base my development on.
I know the view is well built and does not throw errors because I use it in other instances.
<script defer>
let select = document.getElementById("sort-select");
let allNews = document.getElementById("posts-result");
let xhttp = new XMLHttpRequest();
console.log(js_query)
select.addEventListener("change",function(){
xhttp.open("GET", "/api/load-posts-search?sortBy="+ select.value +"&search=" + js_query, false);
xhttp.send();
let news = JSON.parse(xhttp.responseText);
console.log(news);
allNews.innerHTML=""
for(i=0;i<news.total;i++)
{
console.log(news.data[i]);
allNews.innerHTML+=(`#include('partials.news.post',['news'=>`+news.data[i]`])`)
}
})
</script>
The XMLHttpRequest will be asynchronous, so I think you need to change this:
select.addEventListener("change",function(){
xhttp.open("GET", "/api/load-posts-search?sortBy="+ select.value +"&search=" + js_query, false);
xhttp.send();
let news = JSON.parse(xhttp.responseText);
console.log(news);
allNews.innerHTML=""
for(i=0;i<news.total;i++)
{
console.log(news.data[i]);
allNews.innerHTML+=(`#include('partials.news.post',['news'=>`+news.data[i]`])`)
}
})
to:
select.addEventListener("change",function(){
xhttp.open("GET", "/api/load-posts-search?sortBy="+ select.value +"&search=" + js_query, false);
xhttp.send();
// wait on the response from the request
xhttp.onload = function() {
let news = JSON.parse(xhttp.responseText);
console.log(news);
allNews.innerHTML=""
for(i=0;i<news.total;i++)
{
console.log(news.data[i]);
allNews.innerHTML+=(`#include('partials.news.post',['news'=>`+news.data[i]`])`)
}
}
})
I'm not sure about using the #include within the JavaScript, it's not something I've done to know how well it would work. If the included blade file was static I think it would be fine, I'm just not sure how it would work passing it a dynamic news property that comes from an ajax request, i.e. one part of the #include is server side and one is client side, but I could be wrong and it will work completely fine.
You might need to refactor and return the html of the generated partial from the controller instead of trying to do it within the success stage of the ajax request.
Related
I want to view and manipulate Javascript localStorage information on a PHP page using PHP. I have gotten pretty far with this, but I'm not where I need to be. I'm using PHP 7.3 and vanilla JS.
I have AJAX POSTing the data to a PHP processing page (not the one that calls the javascript function). However, I need to access the POST variable on the page that called the javascript. How can I pass the information back without a click?
The page wishlist.php contains a link to the js file and <div id="temporary_wishlist"></div>.
Javascript called from wishlist.php:
window.addEventListener("load", function() {
loadWishlist();
});
// get wishlist contents
function loadWishlist() {
var items = wishlistStorage.data.items.join("%20");
var item_notes = wishlistStorage.data.item_notes.join("%20");
var comments = wishlistStorage.data.comments;
var wishlistRequest;
var response = null;
if(window.XMLHttpRequest) {
wishlistRequest = new XMLHttpRequest();
} else {
wishlistRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
wishlistRequest.onreadystatechange = function() {
if(wishlistRequest.readyState == 4 && wishlistRequest.status == 200) {
response = wishlistRequest.responseText;
document.getElementById("temporary_wishlist").innerHTML = response;
}
}
wishlistRequest.open("POST", "/wishlist-processor.php", true);
wishlistRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
wishlistRequest.send("wishlist_items=" + encodeURIComponent(items)
+ "&wishlist_itemnotes=" + encodeURIComponent(item_notes)
+ "&wishlist_comments=" + encodeURIComponent(comments));
}
Given the above, I have access to $_POST['wishlist_items'] inside wishlist-processor.php. Whatever I output inside of wishlist-processor.php is visible to the visitor on wishlist.php inside <div id="temporary_wishlist"></div>. It is not, however, visible in the Console.
On wishlist.php, I want to load the information into a PHP variable so I can send it to a MySQL query. If I could just POST to self like I do with form validation I would have access to $_POST['wishlist_items'] from wishlist.php. I already tried setting the URL in the open("POST", URL, true) function to _self or wishlist.php, and that didn't work for me.
I know it's suggested that I use Fetch, but I'm already overwhelmed learning new things I want to understand AJAX better. Also, Fetch doesn't work on Firefox Android.
I've been looking at how to integrate AJAX calls into a Python Django application and I'm somewhat new to both. I have been following the advice here:
https://www.quora.com/Can-I-execute-a-Python-function-from-JavaScript
Which led to this and this respectively for AJAX and Django advice.Both made pretty good sense to me. The desired end result is that a template in this fourth folder down (dashboard) call a function in a file called logic.py under the api folder above it:
In a JavaScript file hooked up to my django template, I have the following code I stole from the AJAX resource I listed above and made some light edits to:
window.onerror = function() {
debugger;
}
// browser - safety
var request;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else if(window.ActiveXObject) { // ie
try {
request = new ActiveXObject('Msxml2.XMLHTTP');
}
catch(e) {
try {
request = new ActiveXObject('Microsoft.XMLHTTP');
}
catch(e) {}
}
}
function step2() {
console.log('something');
}
function testLogin() {
request.open('POST', '../../../api/logic');
// I've also been trying ^^^ logic.py, if it matters
request.send(null);
console.log('testLogin ran');
step2();
}
request.onreadystatechange = function () {
if(request.readystate === 4) {
if(request.status === 200) {
console.log(request.responseText);
}
}
}
It still is hooked up to a URL POST action in the django views, so when I hit the submit button in question I see the following two requests get generated:
That is the correct filepath for that location:
So I'm wondering if I'm missing something either about the AJAX setup, or the way it needs to interact with Django, or some combination of the two. Other resources I've been consulting in looking into this:
Call Python function from Javascript code
https://codehandbook.org/python-flask-jquery-ajax-post/
https://www.makeuseof.com/tag/python-javascript-communicate-json/
https://bytes.com/topic/javascript/answers/737354-how-call-python-function-javascript
And I originally started way earlier in the day so there were a few more, but needless to say I didn't see my issue immediately from looking at any of them. Any help is much appreciated.
So this wound up being a quirk of the Django url setup, I can't believe I didn't figure it out but I hadn't been in that part of the code base for some time.
In our urls.py script, the place I was pinging (which was in the location of the URL described) had a redirect on it and for that reason, the traffic wasn't going to the place I thought.
Spark has been acting weird lately. I have a button which when clicked calls a POST method with some query parameters:
post("/test", (request, response) -> {
model.put("reason", "some reason here");
...
LOG.info("Returning from /test with reason: " + model.get("reason"));
// the above line always executes and always prints the correct output (never 404)
return new ModelAndView(model, "test.vtl");
}, new VelocityTemplateEngine());
The file test.vtl contains only this: $reason
(which is used in the JS code below to show an alert with the contents of the reason key in the model map).
JS relevant code:
xmlHttp.open("POST", "/test", true);
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var params = "file=" + file + "&searchStr=" + searchStr;
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == XMLHttpRequest.DONE) {
alert(xmlHttp.responseText);
}
}
xmlHttp.send(params);
When I click it, sometimes it work perfectly, and when I click again I get a 404 Not Found with:
MatcherFilter:152 - The requested route [/test] has not been mapped in Spark
This happens in a matter of seconds. I click - it works - I click again if fails - again it fails - again it fails - again it suddenly succeeds...
How can that be?
P.s. I have logging inside the post request, so I know Spark is actually accessing it. But it is not returning from it. Does this perhaps have to do with the code inside the post that suddenly raises the 404 (I am not accessing other pages from it though).
There seem to be 2 possible answers to this (why do they solve is a different question):
Adding a Thread.sleep(250); // or even lower.
Changing the request to GET.
I could not find what is the root cause of these arbitrary failures, but ended up choosing option #2.
So I have a json html link that like below
www.pretendJsonLink.com/getData
and the data i receive is below:
{"Items":[{"date":1498850140373,"displayId":"003","sentId":"121213",
"customer":"ME"}, {"date":1452870140571,"displayId":"007","sentId":"152713",
"customer":"YOU"}],"Count":2,"ScannedCount":2}
I need to load this into a js file so i can then call them as needed in a html file in an id="" tag
Like Items.date and Items.customer or something like it
Any help would be great and I understand that this should be a simple task, but i can also forward my search history as well :) i have been looking for solutions that work, but just cant seem to find anything that fits my needs
Use JSON.parse() function. Here is the link to documentation
You can use XMLHttpRequest . I found a gist that gives a good example and included it (simplified), below:
var req = new XMLHttpRequest();
req.open('GET', 'www.pretendJsonLink.com/getData');
req.onload = function() {
if (req.status == 200) {
// do what you want, here, with the req.response
// take a look at the object that gets returned, you may need
// to call JSON.parse(), etc.
console.log('success', req.response);
} else {
console.log('error', req.statusText);
}
};
// Handle network errors
req.onerror = function() {
console.log("Network Error");
};
// Make the request
req.send();
I'm using AHAH (as outlined here http://microformats.org/wiki/rest/ahah) to make two calls to populate HTML on a page. The calls happen after the document is ready and are fired off one after another. The result, every time, is the first call gets overwritten with the last calls response. So I'll have two of the same chunks of HTML on the page instead of two unique pieces of code. Sometimes the first call doesn't even get to evaluate it's call back and thus remains empty.
Any ideas?
If you're using the exact code on that page, it's not surprising, as the example there uses a single global variable to store the XMLHttpRequest being made. So there's no way it can work for more than one simultaneous request: calling the function a second time overwrites the req with a new one, causing the req read by ahahDone to be the wrong request.
If you want to allow this you'll have to make req a local variable (by declaring it var in function ahah()), and pass it with the target to the ahahDone() function. Or just do it inline:
function Element_loadHTML(element, url) {
var req= null;
if (window.XMLHttpRequest) {
req= new XMLHttpRequest();
} else if (window.ActiveXObject) {
try {
req= new ActiveXObject('MSXML2.XMLHttpRequest');
} catch() {}
}
if (!req) {
element.innerHTML= 'Browser does not support XMLHttpRequest';
return;
}
element.innerHTML= 'Loading...';
req.onreadystatechange= function() {
if (req.readyState===4)
element.innerHTML= req.status===200? req.responseText : 'Error '+req.status;
};
req.open('GET', url);
req.send(null);
}
Element_loadHTML(document.getElementById('appdata'), 'appdata.part.html');
Element_loadHTML(document.getElementById('foo'), 'bar.part.html');
The stuff with the browser sniffing and trying to execute script tags is hopeless and broken; don't use it. It's not good practice to be loading <script> element content into the page.