I am creating a web app that consumes the https://restcountries.eu/ API.
When a user types a country, I'll make a request to the API using fetch. However, my requests always get canceled.
I tested the part which captures user input, but I think the problem is with my fetch code.
var countryName; // This will receive the user input on a textbox in my HTML file.
var resultado;
function grabCountry(urlendpoint, countryName, endpointfields) {
countryName = document.getElementById('searchInput').value;
var urlendpoint = 'https://restcountries.eu/rest/v2/name/';
var endpointfields = '?fields=topLevelDomain;alpha3Code;callingCodes;altSpellings;subregion;population;latlng;languages;flag';
fetch(urlendpoint + countryName + endpointfields)
.then(response => data)
.then(data => {
console.log(data())
})
}
One of the reasons for cancelled fetch calls can be that the HTML tag that triggers the event is a child (or grandchild) of an HTML Form tag. In that case the event might trigger the form which will start submitting the form data, thus it will naturally cancel your fetch call.
One of the solutions is to call preventDefault function on the event that triggers the fetch call. See example below:
function myFetchFunction(event) {
event.preventDefault();
fetch("https://my-url-here");
}
<button onclick="myFetchFunction">Fetch</button>
The code you've provided so far works just fine. You need to examine how you get your data. It should look like this for text or the .json() for parsing json.
fetch('/url')
.then(response => response.text())
.then(data => console.log(data));
Here's a demo:
var countryName; // This will receive the user input on a textbox in my HTML file.
var resultado;
function grabCountry() {
countryName = 'Bulgaria';
var urlendpoint = 'https://restcountries.eu/rest/v2/name/';
var endpointfields = '?fields=topLevelDomain;alpha3Code;callingCodes;altSpellings;subregion;population;latlng;languages;flag';
fetch(urlendpoint + countryName + endpointfields)
.then(response => response.json())
.then(data => console.log(data))
}
grabCountry();
Please do change the button type from submit to button. Your fetch will work like a charm!
<button type=button onClick="javascript:ticketCreation(document.getElementById('domain').value);">
Your fetch code has a syntax error near the first then close.
var countryName; // This will receive the user input on a textbox in my HTML file.
var resultado;
function grabCountry(urlendpoint, countryName, endpointfields) {
countryName = document.getElementById('searchInput').value;
var urlendpoint = 'https://restcountries.eu/rest/v2/name/';
var endpointfields = '?fields=topLevelDomain;alpha3Code;callingCodes;altSpellings;subregion;population;latlng;languages;flag';
fetch(urlendpoint + countryName + endpointfields).then(function(data){
console.log(data)
})
}
grabCountry('', '' , '')
<input type="text" id="searchInput" value="united" />
Related
I am getting undefined when I type the author name in the text box and press the button to display the quote. It seems like my button and textbox are not linked together. How can I fix this?
<!DOCTYPE html>
<html lang="en">
<head>
<title>Quotes</title>
</head>
<body>
<label for="getQuotes">Find Quotes (Type Author Name)</label><br>
<input type = "text" id="getQuotes" name="getQuotes" placeholder="Search" style="margin:10px" size="50"/><br />
<button id="FetchQuotes" onclick="getQuote()" style="margin:10px">Fetch Quotes</button>
<p id="quotes"></p>
<p id="author"></p>
<script>
async function getQuote() {
//const author = Boolean(false);
let url = 'https://jaw1042-motivate.azurewebsites.net/quote';
let author = document.getElementById('getQuotes').value;
if(author) {
url = 'https://jaw1042-motivate.azurewebsites.net/quote?author= ';
console.log(url + author);
} else {
console.log(url);
}
fetch(url)
.then(async (response) => {
if (response.ok) {
console.log("Response code: " + response.status);
} else if (response.status === 400) {
console.log("Unable to find any quotes by specified author: " + response.status);
} else {
console.log("No quotes have been loaded: " + response.status);
}
const val = await response.json();
console.log(val);
}).then(data => {
document.getElementById('quotes').value = data;
document.getElementById('author').value = data;
console.log(data);
alert(data);
});
}
</script>
</body>
</html>
your then functions are not correct
in the direct result of the fetchAPI you can receive data and to use it you need to run .json() or .text() on it, you can't simply use that result or return it's value ( plus when you use return statement all your next codes will be unreachable)
after that you should not assign something to your data variable because it just has new Data fetched from backend, by assigning new value to data you're about to ruin new data
here is how your js should look
function getQuote() {
fetch("https://krv1022-motivate.azurewebsites.net/quote")
.then( res => res.text() )
.then( data => {
document.querySelector(".quote").value = data;
}
);
}
I also provided a fiddle for it but it can't receive data because either your URL is not correct or there is CORS issues
==============================================
one thing that I just noticed, you are receiving Author's name from end user but you are not about to send it to backend!
so perhaps this code is more complete, I assume that you want to send data using GET method and backend wants the name of author to be named getQuotes
I have a registration form, the user is being redirected to home.php after success (works)
But also all the 'alerts/errors' which are echos in PHP, after submit, will redirect to register.php and show the error in blank white page.
(How do i display them to <div class="msg"> position?)
<script>
document.querySelector(".register form").addEventListener("submit", async (e) => {
e.preventDefault()
const form = e.target
const body = new FormData(form)
// fetch is much easier to use than XHR
const res = await fetch(form.action, {
method: "POST",
headers: {accept: "application/json", // let PHP know what type of response we want},
body})
const data = await res.json()
if (res.ok) {
location.href = data.location
} else if (res.status === 400) {
document.querySelector('.msg').textContent = data.message
// also do something with data.errors maybe
}
})
</script>
<body>
<div class="msg"></div> <!--position for error/ wrong pass etc-->
register.php
Based off that, please provide a correct code snippet in order to mark this as resolved.
It would probably make your life quite a bit easier if you always returned JSON from your PHP, rather than sometimes HTML as well.
For examples, when checking the errors at the top of register.php, you should return JSON objects --- e.g.
{error: "Email is not valid!"}
rather than their HTML equivilents.
This means that in your fetch, you'll now always be able to get the JSON content (currently, you'd probably get an error in your browser's debug console if one of those messages came back, as it's not valid JSON). Then, in your JavaScript, you can just detect this and switch however you want:
if (data.error) { // If there is an error
document.querySelector(".msg").textContent = data.error;
}
else if (data.location) { // If we want to redirect the user somewhere
window.location.href = "./" + data.location;
}
Per Pushbullet API doc I need: Header as: 'Access-Token: o.I'veLearnedNotToPost' 'Content-Type": "application/json' Url is https://api.pushbullet.com/v2/users/me
Problem with my code (don't laugh too hard) is that it only returns "Retrieving information for o.I'veLearnedNotToPost"
Front end code needs to take token from user input text element and put it in backend code (getuser.jsw) to fetch User Info. But the issue is that it's not - nothing except the placeholder text appears in the textbox element (id #result)
Side note: $w is Wix's write to element
// FRONT END CODE
import {getUserInfo} from 'backend/getuser';
export function button1_click(event, $w) {
console.log("Retrieving information for " + $w("#sendToken").value);
getUserInfo($w("#sendToken").value)
.then(usInfo => {
($w("#result").text)
});
}
//BACKEND CODE
import {fetch} from 'wix-fetch';
export function getUserInfo(token) {
let atoken = token;
let url = "https://api.pushbullet.com/v2/users/me";
console.log("Retrieving information for " + atoken);
return fetch("https://api.pushbullet.comm/v2/users/me", {
headers: {
"Access-Token": atoken,
"Content-Type": "application/json"
}
.then(response => response.json())
})}
Thanks in advance for your help!
Greatly appreciated!
-Malc
your Access-Token value is double quoted, try without.
I currently have a servlet setup to send over a list of our active servers. The method grabs the servlet data, processes it, then injects the html into the datalist tag. HTML injection process works, but when I'm splitting the array by the concat separator (which I've done before), I get no values. Below I'll explain with code examples:
HTML:
<label for="server_id_text">Server ID: </label>
<input id="server_id_text" list="server_names" name="server_id" required>
<datalist id="server_names">
<!--This gets injected with the active servers grabbed through a get request-->
</datalist>
Javascript connecting to server to get data:
Note: serverList is a global variable.
var serverList = "";
function setupAutoComplete() {
$.get(baseURL + "/SupportPortal", function (data, status) {
console.debug("Status with auto comp id: " + status);
serverList = data;
console.debug("server list auto comp at post mailing: " + serverList);
});
}
This method is called in the function that is called when the onload event is called in the body tag
Here are the two methods that inject the html:
function setupServerName() {
document.getElementById("server_names").innerHTML = getServerListHTML();
}
function getServerListHTML(){
console.debug("Autocomplete process running...");
var servArr = String(serverList).split('*');
var html = '';
var temp = '<option value="{serverName}">';
console.debug("Array:" + servArr.toString());
if (serverList == 'undefined' || servArr.length == 0){
console.debug("serverList is empty...");
return '';
}
for (var i =0; i < servArr.length; ++i){
html += temp.replace("{serverName}", servArr[i]);
}
console.debug("html: " + html);
console.debug("ServList size " + servArr.length);
return html;
}
When the page loads, setupAutoCompelte() is called first. Then, setupServerName() is called.
My issue is that after I load the page, I get the correct response from the server. For instance, I'll get server1*server2 as a response to the jQuery $.get(...) call. Then I go to split the string into an array, and I get back an empty html tag (<option value="">);
Also, the debug console info are as follows:
Autocomplete process running...
Array:
html: <option value="">
ServList size 1
Status with auto comp id: success
server list auto comp at post mailing: server1*server2
Thanks for the help!
I believe that your setupServerName() function is being called before the AJAX request in setupAutoComplete() returns, so your serverList is an empty string at that point. What you need to do is populate your <datalist> from inside your AJAX callback in setupAutoComplete().
// setup autocomplete datalist
function setupAutoComplete() {
var $datalist = $('#server_names');
$.get(baseURL + '/SupportPortal').then(function (data) {
// update datalist
if (!data || !data.length) {
// no servers, empty list
$datalist.html('');
} else {
// create options html:
// reduce array of server names
// to HTML string, and set as
// innerHTML of the dataset
$datalist.html(data.split('*').reduce(function (html, server) {
return html + '<option value="' + server + '">\n';
},''));
}
});
}
// on page load, setup autocomplete
$(function () {
setupAutoComplete();
});
As you can see from "debug console info":
the get function is asyncrhonous so you need to change your setupAutoComplete get part to:
$.get(baseURL + "/SupportPortal", function (data, status) {
console.debug("Status with auto comp id: " + status);
serverList = data;
setupServerName();
console.debug("server list auto comp at post mailing: " + serverList);
});
On page load try to call directly the setupServerName function within the success event of get function. A different approach is to divide the setupServerName function so that the part related to the serverList variable becomes part of another function.
The serverList variable is global but its content is filled after the setupServerName is executed.
My ASPX code generated some html files where I just put link for paging like
First |
Next |
Previous |
Last
say if user currently on second page when it press Next moves to 3rd page ...
now issue is when user clicking Next button several times and system is in progress to generate let say 5th page it will show error page.
Is there any way to check from html via javascript to check whether file is present or not?
Kindly help me to pull out from this show stopper issue
You can use ajax for check file exists or not
Using Jquery
$.ajax({
url:'http://www.example.com/3.html',
error: function()
{
alert('file does not exists');
},
success: function()
{
alert('file exists');
}
});
Using Javascript
function checkIfRemoteFileExists(fileToCheck)
{
var tmp=new Image;
tmp.src=fileToCheck;
if(tmp.complete)
alert(fileToCheck+" is available");
else
alert(fileToCheck+" is not available");
}
Now to check if file exists or not call js function like this
checkIfRemoteFileExists('http://www.yoursite.com/abc.html');
i like to use this type of script
function CheckFileExist(fileToCheck: string) {
return new Promise((resolve, reject) => {
fetch(fileToCheck).then(res => {
if (res.status == 404) resolve(false);
if (res.status == 200) resolve(true);
return res.text()
})
})
}
and use it
var exists = await CheckFileExist(link);
There is an issue with #Sibu's solution: it actually downloads the file (it can be potentionally big, wasting traffic)
In the 2021, one should not use jQuery in new projects
native Promises and Fetch are the way to go today
<output id="output"></output>
<script>
// create a non-cached HTTP HEAD request
const fileExists = file =>
fetch(file, {method: 'HEAD', cache: 'no-store'})
.then(r => r.status==200);
// check the file existence on the server
// and place the link asynchronously after the response is given
const placeNext = file => fileExists(file).then(yes => output.innerHTML =
(yes ? `Next` : '')
);
// place the "next" link in the output if "3.html" exists on the server
placeNext('3.html');
</script>