How do I display value(s) of fetch function? - javascript

I'm struggling to extract certain data values and put them in my website. I'm getting data from an API in JSON format. This is then handled by the handleResponse function. Now I wish to display one or more of these received values on my website. Any clues on how to properly do this? I've tried just about everything to the best of my ability. I am also aware that {dataList} is currently not a used variable. This is just to state where i want my data to be. Thanks.
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Sollicitatie Opdracht Volcano</title>
<link rel='icon' type='image/png' href='/favicon.png'>
<link rel='stylesheet' href='/global.css'>
<link rel='stylesheet' href='/build/bundle.css'>
<script defer src='/build/bundle.js'>
import { onMount } from "svelte";
// Here we define our query as a multi-line string
// Storing it in a separate .graphql/.gql file is also possible
var query = `
query ($id: Int) { # Define which variables will be used in the query (id)
Media (id: $id, type: ANIME) { # Insert our variables into the query arguments (id) (type: ANIME is hard-coded in the query)
id
title {
romaji
english
native
}
}
}
`;
var dataList;
// Define our query variables and values that will be used in the query request
var variables = {
id: 15125
};
// Define the config we'll need for our Api request
var url = 'https://graphql.anilist.co',
options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({
query: query,
variables: variables
})
};
// Make the HTTP Api request
fetch(url, options).then(handleResponse)
.then(handleData)
.catch(handleError);
function handleResponse(response) {
return response.json().then(function (json) {
return response.ok ? json : Promise.reject(json);
});
}
function handleData(data) {
console.log(data);
}
function handleError(error) {
alert('Error, check console');
console.error(error);
}
</script>
<h1>API Fetching System</h1>
<main>
<h2>{dataList}</h2>
</main>
<svelte:head>
<title>aniAPI Test App</title>
</svelte:head>
<style>
main {
background-color: lavenderblush;
font-size: 15px;
}
h1 {
font-size: 25px;
}
</style>
Data to display:

I fixed the issue.
By declaring a var dataString = ''; in the beginning, and in the HandleData function, I stringify the data using dataString = JSON.stringify(data);
then down below where dataList used to be:
{#await dataString}
{:then dataString}
<h2>{dataString}</h2>
{/await}

Related

How to send information in frontend with POST to backend with Gin and Go

I normally send data within forms, and never had any problem, but now I need to send the data with JavaScript, and I am not able to read it in the backend.
My main.go file:
package main
import (
"encoding/json"
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// We create the instance for Gin
r := gin.Default()
// Path to the static files. /static is rendered in the HTML and /media is the link to the path to the images, svg, css.. the static files
r.StaticFS("/static", http.Dir("../media"))
// Path to the HTML templates. * is a wildcard
r.LoadHTMLGlob("*.html")
r.NoRoute(renderHome)
// This get executed when the users gets into our website in the home domain ("/")
r.GET("/", renderHome)
r.POST("/", getData)
r.Run(":8080")
}
func renderHome(c *gin.Context) {
c.HTML(http.StatusOK, "my-html.html", gin.H{})
}
func getData(c *gin.Context) {
formData := &struct {
Name string `json:"mydata" binding:"required" `
}{}
// Validation (with Gin)
if err := c.Bind(formData); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
fmt.Print(err)
return
}
fmt.Println("formData: ", formData.Name)
dec := json.NewDecoder(c.Request.Body)
fmt.Println("Decooder: ", dec)
dec.Decode(formData)
fmt.Println("formData: ", formData.Name)
p := c.PostForm("mydata")
fmt.Println("Params: ", p)
p = c.Params.ByName("mydata")
fmt.Println("Params: ", p)
p, _ = c.Params.Get("mydata")
fmt.Println("Get: ", p)
fmt.Println("Body: ", c.Request.Body)
}
My HTML file, located in the same directory:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body onload="afterLoad()" style="background-color: pink">
<script>
async function postData(url = "", data = {}) {
// Opciones por defecto estan marcadas con un *
const response = await fetch(url, {
method: "POST",
mode: "cors",
cache: "no-cache",
credentials: "same-origin",
headers: {
// "Content-Type": "application/json",
"Content-Type": "application/x-www-form-urlencoded",
},
redirect: "follow",
referrerPolicy: "no-referrer",
body: JSON.stringify(data),
});
return response.json(); // parses JSON response into native JavaScript objects
}
function afterLoad() {
postData("/", { mydata: 42 }).then((data) => {
console.log(data); // JSON data parsed by `data.json()` call
});
}
</script>
</body>
</html>
I tried to interchange the headers from application/json to application/x-www-form-urlencoded but no luck.
The answer I get in the console after reloading the page in the browser (and the method afterLoad() from JavaScript gets executed) is:
formData:
Decooder: &{0xc0002b7580 [] {[] 0 0 {<nil> false [] <nil> 0} {<nil> []} <nil> false false} 0 0 {<nil> false [] <nil> 0} <nil> 0 []}
formData:
Params:
Params:
Get:
This data is printed from the getData() func in main.go file. What I am doing wrong to not be able to get the data?
I see two problems. First, formData is a pointer to struct and when you use decode you get the address of something that's already an address. Second, your struct doesn't have a json tag with mydata, just a form tag, which is not enough for json.Decode to map the json attribute to the struct attribute. Change the form tag for a json tag

Embedded BPMN editor needs a working download button with django

Currently I have a HTML Page which is embedding a BPMN Modeler via https://bpmn.io/.
They way it works is that I've an empty .bpmn file in my media directory and everytime I visit my page e.g. it loads the empty .bpmn file and the user is free to model his own diagram from there.
Now I'd like for the user to be able to download his .bpmn file which he created on the page.
I've never worked with JS and Django before. I don't really know how to pass my modified .bpmn diagram back to my django view downlad function.
Let me show the code I've so far, starting with the bpmn.io script which enables the user to work with the diagram(modeler.html):
<link rel="stylesheet" href="https://unpkg.com/bpmn-js#8.0.0/dist/assets/diagram-js.css"/>
<link rel="stylesheet" href="https://unpkg.com/bpmn-js#8.0.0/dist/assets/bpmn-font/css/bpmn.css"/>
<script src="https://unpkg.com/bpmn-js#8.0.0/dist/bpmn-modeler.development.js"></script>
<script>
function fetchDiagram(url) {
return fetch(url).then(response => response.text());
}
var bpmnJS = new BpmnJS({
container: '#canvas',
width: '100%',
height: '600px',
});
async function openDiagram() {
const diagram = await fetchDiagram('static/bpmn/empty_bpmn.bpmn');
try {
await bpmnJS.importXML(diagram);
viewer.get('canvas').zoom('fit-viewport');
} catch (err) {
console.error('something went wrong:', err);
}
}
openDiagram();
</script>
and the belonging view functions to this(views.py):
def modeler(request):
return render(request, 'core/modeler.html')
def download_bpmn(request):
response = HttpResponse(content_type='application/bpmn')
response['Content-Disposition'] = 'attachment; filename="your_diagram.bpmn"'
return response
the download button(modeler.html):
<div class="col-2">
<a class="btn btn-primary" href="{% url 'download_bpmn' %}"> Download </a>
</div>
TLDR:
Is there a way to pass my bpmn diagram back to django so I can create a view function which enables the user to download his diagram?
I used ajax to do that. I send the XML to a view that creates and saves the document in a model that has a FileField, then you can provide the url of the document to the user.
AJAX:
async function exportDiagram() {
const csrftoken = getCookie('csrftoken');
try {
var result = await bpmnModeler.saveXML({ format: true });
$.ajax({
type: 'POST',
url: url,
headers: {'X-CSRFToken': csrftoken},
data: {'data' : result.xml},
success: function(response){
},
})
}
catch (err) {
console.error('Erro ao salvar BPMN 2.0', err);
}
}
$('#save-button').click(exportDiagram);
VIEW:
def modeler(request, pk):
if request.method == "POST":
content = request.POST.get('data')
bpmn = Bpmn()
bpmn.Filefield.save(f'{diagrama.titulo}.bpmn', ContentFile(content))
return render(request, 'bpmn.html')

Picking random image from array 60+ choices javascript

I understand this question has tons of answers already, but I am trying to figure out how to do this in the most efficient way. I have a website that sends an image with a button click to a phone number, but I want to choose between 60 or so photos and manually entering all of these image locations into an array does not seem ideal.
Here is my js file that performs the email action, this is all hosted on a free hosting service.
// server.js
const express = require("express")
const app = express()
app.use(express.static("public"))
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html")
/* this sends the "index.html" file when people go to app.glitch.me/ */
})
app.get("/send", (req, res) => {
// where node app starts
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.USER,
pass: process.env.PASS,
}
});
var mailOptions = {
from: process.env.USER,
to: process.env.RECIP,
subject: "As you requested",
text: '',
attachments: [
{
/*image location*/
path: 'https://post.healthline.com/wp-content/uploads/sites/3/2020/02/322868_1100-1100x628.jpg',
}
]
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
res.redirect("/sent.html") // after sending the email, redirect back to "index.html" at app.glitch.me/
})
app.listen(3000); //open for traffic
Here is my HTMl if its even relevant to my question
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello!</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- import the webpage's stylesheet -->
<link rel="stylesheet" href="/style_index.css">
click me for snazzy pics<!-- script to ping --!>
<!-- import the webpage's javascript file -->
<script src="/script.js" defer></script>
</head>
<body>
<h1>hello</h1>
<p>
I made this.
</p>
</body>
</html>
Try first logging all of your images from where they are hosted. If it is not a database you can call upon then you may need to create an array of them manually. Once they are in an object, you can simply use a variable to determine which position in the array that image link should come from. I hope the below helps.
For example:
imageChoices = ["https://post.healthline.com/wp-content/uploads/sites/3/2020/02/322868_1100-1100x628.jpg", "https://post.healthline.com/wp-content/uploads/sites/3/2020/02/322868_1100-1100x628.jpg", etc.]
randomIndexChooser = Math.floor(Math.random() * 60) + 1;
var mailOptions = {
from: process.env.USER,
to: process.env.RECIP,
subject: "As you requested",
text: '',
attachments: [
{
/*image location*/
path: imageChoices[randomIndexChooser],
}
]
};
you need to make an ajax service that calls an api, the api loops through all the files that are in the specified folder and returns the list of file paths. after you get the list from the api, you append them to the wanted array in your javascript code.
I will provide you a sample in asp.net c# , you may be working on another framework, but you can benefit from the idea at least.
here is a function in an api
[HttpGet]
public List<string> GetImageFilesPaths()
{
//getfiles returns all found files' paths in a specified directory
List<string> imageFilePaths = Directory.GetFiles("folderpath", "*.png", SearchOption.AllDirectories).ToList();
}
ajax service that calls the API
$.ajax({
url:'hostname/apiname/GetImageFilesPaths'
contentType: "application/json",
dataType: 'json',
success: function(result){
//here you append the result which is the list of file path
//into your wanted array, you can also loop
result.forEach((imagePath)=>{
arrayOfImages.push(imagePath)
})
}
})

Loading images in vue.js from an API

Consider this:
An API loads a manifest of image metadata. The images have an ID, and with another API call returns a base64 image from the DB. The model for the manifest is attachmentRecord and the ID is simply a field.
I would rather not preload these large strings into an array (that would work).
so I have this (which lazy loads on any manifest change):
<div v-for="(attachment, index) in attachmentRecord" :key="index">
<img :src="fetchImage(attachment.id)" />
</div>
fetchimage() is a wrapper for an axios function which returns back from a promise. (writing this from memory):
this.axios({
method: "get",
url: url,
}).then(res => res.data)
.catch(() => {
alert("Unable to load raw attachment from this task and ID");
});
}
Now, the network calls go thru fine, the ID passes in correctly, I can see the base 64data, but they don't seem to make it to wrapper function or the src attribute. It always comes up blank. I tried wrapping it in another promise,only to get a promise back to the src attribute. What would be a best practice for this situation in Vue?
Ok, so far I made these changes with Constantin's help:
I tried to strip it down without a helper function:
Vue template Code:
<div v-for="(attachment, index) in attachmentRecord" :key="index">
<img :src="getAttachmentFromTask(attachment.id)" />
base method:
async getAttachmentFromTask(attachmentID) {
if (!attachmentID) alert("Unknown Attachment!");
let sendBack = "";
let url = "/server/..."
await this.axios({
method: "get",
url: url
})
.then(res => {
sendBack = res.data;
})
.catch(() => {
alert("Unable to load raw attachment from this task and ID");
});
// >>>>>>>>>alerts base64 correctly; Vue loads [object Promise] in img
alert(sendBack);
return sendBack;
}
It turns out that Vue doesn't handle async / await as well as I thought. Therefore, you have to save the image data to each attachment in attachmentRecord. This getAttachmentFromTask method now handles this when accessed the first time and populates a data property for the corresponding attachment object. On successive calls, that property is returned if it is already populated. Note the usage of Vue.set() because the property is not available in the initial data, but we want it to be reactive. You can even set up a fallback image like a loader, see the shortly flickering SO logo without text before the larger logo appears:
new Vue({
el: '#app',
data: {
attachmentRecord: [{
id: 1
}]
},
methods: {
getAttachmentFromTask(attachmentIndex, attachmentID) {
let record = this.attachmentRecord[attachmentIndex];
if (!record.data) {
Vue.set(record, 'data', null);
axios.get('https://kunden.48design.de/stackoverflow/image-base64-api-mockup.json').then((result) => {
Vue.set(record, 'data', result.data);
});
}
return this.attachmentRecord[attachmentIndex].data;
}
}
});
img {
max-width: 100vw;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<div id="app">
<div v-for="(attachment, index) in attachmentRecord" :key="index">
<img :src="getAttachmentFromTask(index, attachment.id) || 'https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon.png'" />
</div>
</div>
old answer: (Unfortunately doesn't work that way with Vue currently)
Axios requests are asynchronous by default. So the function doesn't wait for then() to return the value. You could add the async keyword before your fetchImage function name and add the await keyword before this.axios. Then make the then callback assign the return value to a variable in the fetchImage function scope and have the function return it.
async fetchImage() {
let returnValue;
await this.axios({
method: "get",
url: url,
}).then(res => { returnValue = res.data; })
.catch(() => {
alert("Unable to load raw attachment from this task and ID");
});
return returnValue;
}

Google Place API (Place Details) will not allow GET request, work around [duplicate]

I really do NOT understand how I'm supposed to make this work:
var requestURL = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw';
console.log(requestURL);
$.getJSON( requestURL, function( data ) {
// data
console.log(data);
});
and my HTML file:
<body>
<script
src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
<script src="main.js" charset="utf-8"></script>
</body>
I always get the No 'Access-Control-Allow-Origin' header is present on the requested resource. message... even though if I go to https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw in my browser I get the proper JSON returned.
I am lead to believe that CORS can help me here. I don't understand CORS. Please, can anyone help me in plain simple terms? What should I change to make this work??
Thanks
You are trying to use the Google Places API Web Service on client side whereas it is designed for server side applications. That's probably why appropriate CORS response headers are not set by the server.
As explained in the Notes at the beginning of the Place Details documentation, you should use the Places Library in the Google Maps JavaScript API:
If you're building a client-side application, take a look at the Google Places API for Android, the Google Places API for iOS, and the Places Library in the Google Maps JavaScript API.
Note: you will need to enable the Google Maps JavaScript API in your Google Developer Console first.
Here is a way you can proceed to get place details (based on the example from the documentation):
<head>
<script type="text/javascript">
function logPlaceDetails() {
var service = new google.maps.places.PlacesService(document.getElementById('map'));
service.getDetails({
placeId: 'ChIJN1t_tDeuEmsRUsoyG83frY4'
}, function (place, status) {
console.log('Place details:', place);
});
}
</script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw&libraries=places&callback=logPlaceDetails"></script>
</head>
<body>
<div id="map"></div>
</body>
#rd3n already answered about why to use Google Maps' SDK, but if you really need to use the API instead of SDK on a web app (reuse code, for exemple), you can bypass CORS using proxy parameter from Webpack's DevServer.
const GMAPS_PLACES_AUTOCOMPLETE_URL = (
process.env.NODE_ENV === 'production'
? 'https://maps.googleapis.com/maps/api/place/autocomplete/json'
: 'place-api' // on development, we'll use the Webpack's dev server to redirect the request
const urlParams = new URLSearchParams([
...
])
const response = await fetch(
`${GMAPS_PLACES_AUTOCOMPLETE_URL}?${urlParams}`,
{ method: 'GET' }
)
And on your webpack.config.js...
module.exports = {
devServer: {
proxy: {
'/place-api': {
target: 'https://maps.googleapis.com/maps/api/place/autocomplete/json',
changeOrigin: true,
pathRewrite: { '^/place-api': '' }
}
}
}
}
I know this is an old question, and this might not be a direct answer to this question, but just in case someone could use this trick, I always like to go around this issue using PHP to create my own API, then fetch the newly created API using JavaScript:
1# Create an api.php file:
<?php
$google_URL = 'https://maps.googleapis.com/maps/api/place/details/json';
$api = 'YOUR_GOOGLE_API';
$place = 'PLACE_ID';
$field = [
'user_ratings_total',
'rating'
];
$fields = join(",", $field);
$result_url = $google_URL.'?placeid='.$place.'&fields='.$fields.'&key='.$api;
$result_content = file_get_contents($result_url);
$json_data = json_decode($result_content, true);
if ( isset($json_data) && $json_data['status'] === 'OK' ) {
echo json_encode($json_data['result']);
}else {
echo json_encode($json_data['error_message']);
}
header("content-type: application/json");
2# Create a script.js file:
const url = './api.php';
fetch(url)
.then(res => res.json())
.then(data => console.log(data))
.catch(error => console.log(error))
Using the same url you provided, this is for pure front-end (React), but a less secure solution:
var requestURL = 'https://maps.googleapis.com/maps/api/place/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw';
Cut out the following from url: 'https://maps.googleapis.com/maps/api/place' and create a proxy line in your package.json:
"proxy": "https://maps.googleapis.com/maps/api/place"
Then following google documentations you'll be left with the following code (wherever you're fetching the api):
var axios = require('axios');
var config = {
method: 'get',
url: '/details/json?placeid=ChIJN1t_tDeuEmsRUsoyG83frY4&key=AIzaSyAW4CQp3KxwYkrHFZERfcGSl--rFce4tNw', //the rest of your url
secure: false //important
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});

Categories