Why isn't express's res.render called inside the PUT method? - express

I have an express app with ejs view engine.
In the ejs template, I have a button with an onClick event to trigger a fetch request:
<button class="remove-btn" onclick="removeGroceryItem('<%= index %>')" >Remove</button>
the fetch function
function removeGroceryItem (id) {
fetch('/', {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ groceryItem: id })
})
.then((value)=> console.log(value))
.catch((e)=>console.error(e))
}
The express app route handler:
/* PUT grocery list*/
app.put('/', function(req, res, next) {
groceryItemsContainer.splice(Number.parseInt(req.body.groceryItem), 1)
res.render('index', {
title: 'Express Grocery List App',
notification: 'removed',
groceryList: groceryItemsContainer
})
res.end();
})
The PUT request is received with a status of 200. But the res.render does not seem to be triggered -- why is that??

It appears from your comment that you are expecting the result of your res.render() to display in the browser. That is NOT what an Ajax call using fetch() does from your browser Javascript. It ONLY gets the content back to your Javascript. It does not display anything in the browser.
So, the content you res.render() goes back to your Javascript in your web page and the console.log(value) you have in your Javascript in the web page should actually be showing the content in the console from the res.render(). If you want that content to display in the browser, then you need to insert that content into the current browser DOM yourself with your own Javascript.

Related

Fetch Product variant by SKU works in storefront but not in independent JavaScript program

If I put below script in theme.liquid(Shopify storefront), I get expected result:
<script>
const GRAPHQL_URL = 'https://<my-store>/admin/variants/search.json?query=sku:big-mug-black';
const GRAPHQL_BODY = {
'method': 'GET',
'headers': {
'Content-Type': 'application/json',
},
};
fetch(GRAPHQL_URL, GRAPHQL_BODY)
.then(res => res.json())
.then(console.log)
.catch(console.error);
</script>
But If I try to execute same piece of code from JavaScript program, I get 404({errors: "Not Found"})
const GRAPHQL_URL = `https://<my-proxy>.herokuapp.com/https://<my-store>/admin/variants/search.json?query=sku:big-mug-black`;
const STOREFRONT_ACCESS_TOKEN = '<my-token>';
const GRAPHQL_BODY = {
'method': 'GET',
'headers': {
'Authorization': `Basic ${btoa('<my-api-key>' + ':' + '<my-password>')}`,
'X-Shopify-Storefront-Access-Token': STOREFRONT_ACCESS_TOKEN,
'Content-Type': 'application/json',
},
};
fetch(GRAPHQL_URL, GRAPHQL_BODY)
.then(res => res.json())
.then(console.log)
.catch(console.error);
Note: I can fetch all products using same program, so its not an permission issue. Is there something I need to add/remove to achieve same result in my local JavaScript program? Thank you.
I might have solution just for your need.
You gonna need following accesses:
read_products - for finding product
read_script_tags - for read existing script tags
write_script_tags - for writing new script tag
First on your application create console action that will be run automatically every X hours. That action shall download all existing products. You gonna need save them to local database.
Things to remember during downloading all products.
Api limits watch for them in headers (X_SHOPIFY_SHOP_API_CALL_LIMIT)
Pagination, there is variable link in headers (Api pagination)
When you have stored all products locally, you can create search method for it using SKU.
When you have working method you can create find method in your controller. You will use this method to create request from shopify page to your server.
After creating this you can add JS by yourself or even better automate it with script tags.
ScriptTag on Shopify are basically javascript code that you host on your side and they are automatically loaded TO EACH page in shopify (except basket).
POST /admin/api/2021-01/script_tags.json
{
"script_tag": {
"event": "onload",
"src": "https://djavaskripped.org/fancy.js"
}
}
With that you can add javascript that can be used to create find request on your website. And you can return result back.
I created simplified graph for that.
.

Stripe Checkout does not redirect to checkout page Express

I am trying to use the Stripe prebuilt Checkout page to capture the payment details of an user following this documentation.
I think I wrote the code right, but somehow my app does not redirect the user to the Stripe checkout page. My code is as follows:
In my Express backend:
router.get("/create-check-out", async (req, res, next) => {
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
mode: 'setup',
customer: req.body.id,
success_url: 'http://localhost:5000/ll_profile?session_id={CHECKOUT_SESSION_ID}',
cancel_url: 'http://localhost:5000/ll_profile',
});
res.send (session.id);
});
On my JavaScript client-side:
$.get("/create-check-out", { id: stripe_customer_id}, async (sessionId) => {
console.log(sessionId)
stripe.redirectToCheckout({
sessionId: sessionId,
name: "Yugue"
}).then(function(result) {
console.log(result)
});
The console log does not show sessionId nor result.
The problem is after the get request is sent, the web URL becomes: http://localhost:5000/ll_profile?name= from http://localhost:5000/ll_profile (the URL under which all the codes above live), and the app is stuck at the same page without any redirecting action. I thought that it is supposed to redirect to the Stripe built-in checkout page like this:
What did I do wrong?
Most likely you've got the button inside a <form> element and there is competition between the Checkout redirect and the form submit action. You should either not use a form, or otherwise ensure the click handler related to Checkout is using preventDefault().
If that's not the case, please share more context of your DOM structure and the click handler.

how to redirect from one url to another in vue

I m trying to redirect from one URL to another URL using Vue router eg code
{
path: '/verifyemail/:id/:token',
//can i somelogic here when user entered
},
{
path: '/login',
component:login
},
what I m trying to do? when the user registered himself. server send email verification link to his email when a user clicks on verify button from his email then it should first call verifyemail url. where it has an ajax call with a parameter which i m getting from verifyemail url now after the success it should move to login url note:- i don't have any component in my verfiyemail route
is it possible to do this or is there anyother way to achieve this
The route configuration is only data, so there's not really any way to do this exactly as you'd like.
If you create a component to handle the /verifyemail/ route you can just use this.$router.push(redirectToMe) in it. See the Vue Router docs for more information.
Alternatively, this sounds more like something a backend server would handle on it's own, so maybe you don't even need Vue to worry about it.
finally, I arrive with one solution may be this help other
let start, I send the email with verify button which has link something like "localhost:8080/#/verfiyemail/("ACCESSTOKEN")" NOW I my vue part i does something like
in vue-route
path: '/verifyemail/:uid',
beforeEnter:(to, from, next) => {
let uid=to.params.uid;
next({ path: '/', query: { id: uid}})
}
},
{
path: '/',
name: 'Login',
component: Login,
},
and i my login.vue
created(){
this.verfiyemai();
},
methods:{
verfiyemai(){
var _this=this
var submit=0
if(this.$route.query.id!=undefined ){
if(this.$route.query.id.length<=50){
this.$router.push('/');
submit=1;
}
if(submit==0){
this.$http.get('/api/users/confirm?uid='+this.$route.query.id+'')
.then(function (response) {
console.log(response)
})
.catch(function (error) {
console.log(error)
});
}
}
},
}
from email, I redirect the user to verfiyemail with token id as a parameter from verifyemail route, after that I redirect to the login URL passing the parameter as query and in my login vue I had created a method which checks query length if it greater than 50 then it will post axios response to the server

Call API with Another Api response data in Nuxtjs

Im making a website with Nuxtjs, i want when i open any page of the website to get user information from the server using Axios, and i want to use these information to call another API's from the website.
For example: i will get the User id and Client id from the server and use them on the API URL, lets say i got User id = 5, Client id = 10
i will call another API's and use these informations
http://****/getItems?userid=5&clientid=10
Now my problem is the second API call before the first API finished so i didn't got the user informations yet.
Could you please help me with this issue, note that i want to get the user information on all pages. so if i reload the page in any page i want to get user informations.
So i call the user information API from a Layout and call the other API's from another components.
Thanks.
First you should use Axios module officially provided by Nuxt.js here, https://github.com/nuxt-community/axios-module. They have make the integration between Axios and Nuxt.js easier.
Axios uses promise so you can easily chaining method to do it. Let say you wanna get information from /get/product with data gotten from the url you mention before http://****/getItems?userid=5&clientid=10, you can easily do that like this
this.$axios.$get('/getItems?userid=5&clientid=10')
.then(data => {
// You can use your data received from first request here.
return this.$axios.$post('/get/product', {
id: data.id,
clientId: data.clientId
})
})
.then(data => {
// You can use your data received from second request here.
console.log(data)
})
Explanation
This part,
this.$axios.$get('/getItems?userid=5&clientid=10')
the axios will get the data from the url provided, when the data is received, we can use it within then() block as it accept callback as a parameter.
.then(data => {
// You can use your data received from first url here.
...
})
After that, if you wanna use your data you can easily return the axios request again with proper parameter you wanna send.
return this.$axios.$post('/get/product', {
id: data.id,
clientId: data.clientId
})
And again you can use the data received from second axios request within then() block.
.then(data => {
// You can use your data received from second request here.
console.log(data)
})
Updated
Oke, based on the clarification on the comment section below. We can return the axios promise in first action and then on the second method we can dispatch the first action,
actions: {
callFirst ({ commit }) {
return this.$axios.$get('/get/first')
.then(firstResult => {
commit('SET_FIRST', firstResult)
return firstResult
})
},
callSecond ({ dispatch, commit }) {
return dispatch('callFirst').then(firstResult => {
return this.$axios.$post(`/get/${firstResult.userId}`)
.then(secondResult => {
commit('SET_SECOND', secondResult)
return secondResult
})
})
}
}
Using that way, you just need to put the callSecond() action whereever you want get the second data. And you also don't need to put the callFirst() action on default.vue.

Axios POST request not working when passed object

I am trying to do a post request in a vue js app using axios to a local API and the response is returning empty data. The post request on API is working fine using Postman tool. Below is my code
var the_data = {
title: 'This is title',
description: 'this is description'
}
axios.post('/api/snippets/insert', the_data)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
On the API end, I am using a simple PHP script and printing whole $_POST request data using this code
var_dump($_POST);
But this is returning empty array.
I was running into this as well. Axios does not send the POST data in the form you're expecting. You need something like http://github.com/ljharb/qs and then use axios.post('/api/snippets/insert', Qs.stringify(the_data)). Please note this build on cdnjs uses Qs, not qs.
Alternatives to qs would be e.g. JSON.stringify() or jQuery's $.param().