How to get url from :href in vue and axios? - javascript

I try to send post with vue and axios, from :href element, but I don't know how to fill axios url parament from :href.
I try this:
<div id="follow">
<a :href="'{% url 'follow' recipe.added_by.id %}'" #click="followUser()">Obserwuj</a>
</div>
Href element is fill with Django template tags, and works fine.
My vue and axios code:
methods: {
followUser() {
axios.post()
.then(response => {
console.log(response.data);
})
.catch(errors => {
if (errors.response.status == 401){
window.location = '/login';
}
});
}
},
When I click link, error appear: "TypeError: errors.response is undefined"

You cannot send a POST request via URL because the post parameters are not sent via the URL but you can use an alternate solution and instead of using a link to use a button that looks like a link and is in a form: How to make button look like a link? make-button-look-like-a-link.
have a good day, hope you find it helpful.

You can use destructuration in ES6 to get targeted element, in your case :
<button :href="'{% url 'follow' recipe.added_by.id %}'" #click="followUser">Obserwuj</button>
////
methods: {
followUser({ target }) {
const url = target.getAttribute('href')
axios.post(url)
.then(response => {
console.log(response.data);
})
.catch(errors => {
if (errors.response.status == 401){
window.location = '/login';
}
});
}
},

Related

Alpine JS: x-show not reacting to variable change in async function

I am trying to build a Login-Modal with Alpine JS. The modal is shown initally when opening the page. I define it like:
<div x-data="login()" x-show="showLoginModal" x-cloak x-transition>
<form action="/token" method="POST" class="mt-8" #submit.prevent="submitData">
<!-- defining the login form -->
</form>
</div>
The corresponding Javascript part looks like this (leaving out some variables concerned with the data of the form.):
<script>
let token = undefined
let showLoginModal = false
function login() {
async submitData() {
await fetch(await fetch('/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formBody
})
.then((response) => {
if (response.status === 200) {
return response.json();
} else {
throw new Error("Login failed.");
}
}).then((data) => {
token = data.access_token
showLoginModal = false
})
}
}
</script>
What I am trying to achieve here is that the modal is closed at this point. However although the variable is correctly set to false, the modal stays visible.
I am aware that this has something to do with teh variable being set in an asynchronus function. I do not know how to make it work however and have not found a tutorial that does something similar so far.
All help appreciated.
The problem is that login() function is not a valid Alpine.js component. It does not return any data, so showLoginModal is not reactive, therefore Alpine.js cannot detect when you mutate the value of the variable. A loginComponent using Alpine.data() should look like this:
<div x-data="loginComponent()" x-show="showLoginModal" x-cloak x-transition>
<form action="/token" method="POST" class="mt-8" #submit.prevent="submitData">
<!-- defining the login form -->
</form>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('loginComponent', () => ({
showLoginModal: true,
token: undefined,
async submitData() {
await fetch(...).then((data) => {
this.token = data.access_token
this.showLoginModal = false
})
}
}))
})
</script>
Note that we have to use the this. prefix in the component definition to access Alpine.js data (that are reactive).

How to get access to Wix DB - Blog Posts

So right now I have a homepage, made by using html.
I want to add some divs, where I show the newest blogs I posted on my WIX page.
<div layout="row" layout-align="center center">
<md-card flex="60" class="pad-md md-body-1 border-1" md-colors="{"borderColor": "epprimary1-500", "color": "epsecondary6"}">
{{blog headline}}
Open Blog<md-icon>open_in_new</md-icon>
</md-card>
</div>
On the Wix platform, I know where they store the data in a so called dataset:
Now I need to know how to access these data from my other website.
I figured it out, finally!!
You can get the data you need via an http request.
Therefore, first of all, you need to add a javascript in your backend folder in Wix and name it "http-functions.js", delete it's content and add the folowing code.
Note: get_blogEntry() is method_functionName()
Blog/Posts is the DB I used, you can use any DB you have on wix.
import {ok, notFound, serverError} from 'wix-http-functions';
import wixData from 'wix-data';
export function get_blogEntry() {
let options = {
"headers": {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
}
};
// query a collection to find matching items
return wixData.query("Blog/Posts")
.find()
.then( (results) => {
// matching items were found
if(results.items.length > 0) {
let itemOne = results.items[0];
let itemTwo = results.items[1];
options.body = {
"blogOneTitle": itemOne.title,
"blogOneUrl": "https://etaplus.energy" + itemOne.postPageUrl,
"blogTwoTitle": itemTwo.title,
"blogTwoUrl": "https://etaplus.energy" + itemTwo.postPageUrl
}
return ok(options);
}
})
// something went wrong
.catch( (error) => {
options.body = {
"error": error
};
return serverError(options);
} );
}
After you added this code in your backend, then you can access the data via the following URL:
"https://YOURWEBSITEURL/_functions/blogEntryor whatever your function name is"

How to Login to MediaWiki (Wikipedia) API in Node.js

I'm trying the Wikipedia client login flow depicted in the API:Login docs, but something wrong happens:
1) I correctly get a token raised with the HTTP GET https://en.wikipedia.org/w/api.php?action=query&meta=tokens&type=login&format=json
and I get a valid logintoken string.
2.1) I then try the clientlogin like:
HTTP POST /w/api.php?action=clientlogin&format=json&lgname=xxxx&lgtoken=xxxx%2B%5C
and the POST BODY was
{
"lgpassword" : "xxxxx",
"lgtoken" : "xxxxx"
}
But I get an error:
{
"error": {
"code": "notoken",
"info": "The \"token\" parameter must be set."
},
"servedby": "mw1228"
}
If I try to change lgtoken to token I get the same result.
2.2) I have then tried the old method i.e. action=login and passing the body, but it does not work, since it gives me back another login token: HTTP POST https://en.wikipedia.org/w/api.php?action=login&format=json&lgname=xxxx
and the same POST BODY
I then get
{
"warnings": {}
},
"login": {
"result": "NeedToken",
"token": "xxxxx+\\"
}
where the docs here states that
NeedToken if the lgtoken parameter was not provided or no session was active (e.g. your cookie handling is broken).
but I have passed the lgtoken in the json body as showed.
I'm using Node.js and the built-in http module, that is supposed to pass and keep session Cookies in the right way (with other api it works ok).
I have found a similar issue on a the LrMediaWiki client here.
[UPDATE]
This is my current implementation:
Wikipedia.prototype.loginUser = function (username, password) {
var self = this;
return new Promise((resolve, reject) => {
var cookies = self.cookies({});
var headers = {
'Cookie': cookies.join(';'),
'Accept': '*/*',
'User-Agent': self.browser.userAgent()
};
// fetch login token
self.api.RequestGetP('/w/api.php', headers, {
action: 'query',
meta: 'tokens',
type: 'login',
format: 'json'
})
.then(response => { // success
if (response.query && response.query.tokens && response.query.tokens['logintoken']) {
self.login.logintoken = response.query.tokens['logintoken'];
self.logger.info("Wikipedia.login token:%s", self.login);
return self.api.RequestPostP('/w/api.php', headers, {
action: 'login',
format: 'json',
lgname: username
},
{
lgpassword: password,
lgtoken: self.login.logintoken
});
} else {
var error = new Error('no logintoken');
return reject(error);
}
})
.then(response => { // success
return resolve(response);
})
.catch(error => { // error
self.logger.error("Wikipedia.login error%s\n%#", error.message, error.stack);
return reject(error);
});
});
}//loginUser
where this.api is a simple wrapper of the Node.js http, the source code is available here and the api signatures are like:
Promise:API.RequestGetP(url,headers,querystring)
Promise:API.RequestPostP(url,headers,querystring,body)
If the currently accepted answer isn't working for someone, the following method will definitely work. I've used the axios library to send requests. Any library can be used but the key lies in formatting the body and headers correctly.
let url = "https://test.wikipedia.org/w/api.php";
let params = {
action: "query",
meta: "tokens",
type: "login",
format: "json"
};
axios.get(url, { params: params }).then(resp => {
let loginToken = resp.data.query.tokens.logintoken
let cookie = resp.headers["set-cookie"].join(';');
let body = {
action: 'login',
lgname: 'user_name',
lgpassword: 'password',
lgtoken: loginToken,
format: 'json'
}
let bodyData = new URLSearchParams(body).toString();
axios.post(url, bodyData, {
headers: {
Cookie: cookie,
}
}).then(resp => {
// You're now logged in!
// You'll have to add the following cookie in the headers again for any further requests that you might make
let cookie = resp.headers["set-cookie"].join(';')
console.log(resp.data)
})
})
And you should be seeing a response like
{
login: { result: 'Success', lguserid: 0000000, lgusername: 'Username' }
}
The second post request was where I got stuck for several hours, trying to figure out what was wrong. You need to send the data in an encoded form by using an API like URLSearchParams, or by just typing up the body as a string manually yourself.
I think from what you are saying you have lgtoken and lgname in the URL you are using, and then lgpassword and lgtoken (again!) in a JSON-encoded POST body.
This is not how the Mediawiki API works.
You submit it all as POST parameters. JSON is never involved, except when you ask for the result to come back in that format. I can't help you fix your code as you don't provide it, but that's what you need to do. (If you edit your question with your code, I'll do my best to help you.)
After seeing your code, I'll presume (without knowing the detail of your code) that you want something like this:
return self.api.RequestPostP('/w/api.php', headers, {
action: 'login',
format: 'json',
lgname: username,
lgpassword: password,
lgtoken: self.login.logintoken
});

Vue js computed result not accurate

I am trying to implement a vote button with vue js, when user click "Vote" will send axios request to server and store the data, then return json back. Same with unvote.
I also check if the user is voted, the button should change to Unvote like facebook.
So far the vote and unvote button is work correctly.
But i found a problems which is the voted features is not working. If user voted, after refresh page it will change back to "Vote", but it should be Unvote. But if the button was clicked, in database will showing the vote was deleted. Mean it should be problems of computed. But i am struggle on it since i not really know vue js.
This is my vue components.
<template>
<a href="#" v-if="isLiked" #click.prevent="unlike(comment)">
<span>UnVote</span>
</a>
<a href="#" v-else #click.prevent="like(comment)">
<span>Vote</span>
</a>
<script>
export default{
props: ['comment','liked'],
data: function() {
return {
isLiked: '',
}
},
mounted() {
axios.get('/comment/'+ this.comment.id +'/check', {})
.then((response) => {
this.liked = response.data;//here will get json "true" or "false"
});
this.isLiked = this.liked ? true : false;
},
computed: {
isLike() {
return this.liked;
},
},
methods: {
like(comment) {
axios.post('/comment/'+ comment.id +'/like')
.then(response => this.isLiked = true)
.catch(response => console.log(response.data));
},
unlike(comment) {
axios.post('/comment/'+ comment.id +'/unlike')
.then(response => this.isLiked = false)
.catch(response => console.log(response.data));
},
}
}
Your component instance does not have a liked data property and you should not attempt to set prop values (see https://v2.vuejs.org/v2/guide/components.html#One-Way-Data-Flow)
Also, you are attempting to set the isLiked value outside of the asynchronous operation which will not work how you think.
Just set the isLiked property...
mounted() {
axios.get('/comment/'+ this.comment.id +'/check', {})
.then((response) => {
this.isLiked = response.data; //here will get json "true" or "false"
});
},
Your isLike computed property is also never used.

Using Fetch API with Rails application?

I am trying to use the Fetch API with my Rails application. I can pass parameters to the controller as part of a query string, but still can't figure out how to pass JSON data or where to find it in the controller. A sample call looks like the below. Where can I access my test data on in the controller? Happy Sunday :)
export const fetchControllerData = () => {
return fetch('api/users',), {
body: { "test": "test" }
})
.then(res => res.json());
};
I'm in the process of working out my own issues with fetch and Rails. But I'll take a stab at this.
I expect that fetch is using GET as the default method - which won't use the body at all. You will likely need to set the method to be POST to get the body through. Further to that you might need to set the Content-Type header (to application/json) in order to send the data through as JSON.
May be u need to send params in this way for get request and use this link for https://github.com/axios/axios
export const fetchControllerData = () => {
params = { body: { "test": "test" } }
return HTTP.get('api/users', params)
.then((response) => {
if (response.success) {
// do something here
} else {
// handle error condtion here
}
});
}

Categories