I'm currently building a blog and I'm stuck in the edit article part.
So, on the edit article page I use v-model in order to retrieve the data from the vue store :
<form action="/http://localhost:4000/articles" method="POST">
<div role="button" type="submit" #click="submitArticle">Save</div>
<div class="article-writing__inner" v-for="article in articles">
<div class="title-offset">Title</div>
<input class="input-title" type="text" v-model="article.title"/>
<tinymce id="d1"v-model="article.text"></tinymce>
</div>
</form>
I use a computed property for the v-for loop:
computed: {
articles() {
return this.$store.state.articles
}
}
And finally I send my data to the API with axios like this :
methods: {
submitArticle() {
axios.put('http://localhost:4000/articles/:id', {
title: article.title,
text: article.text,
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
}
As I expected, I can't access the store (v-model) data in axios. In the create article template, I used v-model like below and I managed to post with title: this.title.
data() {
return {
title: "",
text: ""
}
}
How can I bind the v-model from local component data function, or to axios?Or is that another way to do it?
Thank you for your time :)
Article is not set to anything in the the put call to axios. One way to grab your state values in the axios call is to do the following.
submitArticle() {
let vm = this;
axios.put('http://localhost:4000/articles/:id', {
title: vm.article.title,
text: vm.article.text,
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
}
It's all about the scoping of what 'this' is in context of the axios call.
Related
TEMPLATE
<template>
<div class="profile-container">
<div class="theme-container">
<img class="theme" src="#" alt="PH">
</div>
<div class="profile-pic-container">
<img class="profile-pic" :src="responseData.profile_pic" alt="PH">
</div>
<div class="profile-info-container">
<div class="follow-message-button-container">
<button class="direct-message-button btn"><svg><use href="#chat-icon"></use></svg></button>
<Follow v-if="responseData.followers.includes($store.state.userId)"></Follow>
</div>
<h3 class="profile-username">#{{responseData.username}}</h3>
<p class="profile-bio">{{responseData.bio}}</p>
<div class="follower-following-count">
Followers: {{responseData.followers.length}}
Following: {{responseData.following.length}}
</div>
</div>
</div>
</template>
responseData.followers.length works correctly but responseData.followers.includes($store.state.userId) does not. It gives me an error saying:
Cannot read property includes of undefined
SCRIPT
<script>
import Follow from "#/components/Follow";
import getAPICall from "#/mixins/getAPICall";
import getSecondAPICall from "#/mixins/getSecondAPICall";
import Post from "#/components/Post";
export default {
name: "Profile",
components: {Post, Follow},
data() {
return {
list: [],
responseData: {},
responseData2: {},
APIUrl: `api/user/${this.$route.params.userId}`
}
},
methods: {
},
mixins: [getAPICall, getSecondAPICall],
created() {
this.getAPICall(this.APIUrl)
this.getSecondAPICall(`api/user-post-list/${this.$route.params.userId}`)
}
}
</script>
This is what my axios api call looks like
MIXINS
import {getAPI} from "#/axios.api";
import store from "#/store";
export default {
data() {
return {
getAPICall(APIUrl) {
getAPI.get(APIUrl, {headers: {Authorization: `Bearer ${this.$store.state.accessToken}`}}
).then(response => {
this.responseData = response.data
}).catch(err => {
console.log(err)
store.dispatch('useRefreshToken'
).then(_ => {
console.log(_)
getAPI.get(APIUrl, {headers: {Authorization: `Bearer ${this.$store.state.accessToken}`}}
).then(response => {
this.responseData = response.data
}).catch(err => {
console.log(err)
})
}).catch(err => {
console.log(err)
})
}
)
}
}
}
}
When I console log responseData in the created() hook I get an empty proxy.
When I console log it in the mounted hook I get a proxy object with the correct data but if I try to call my API mixins from the mounted hook I still get the same error as before and the rest of my page breaks.
Console logging responseData in the browser returns undefined.
Try to make sure that you have responseData . As vue is first creating the template it is looking for properties in reponseData. And in this case it is not finding the properties. I faced such problems few times. The page is rendered before the api is returing data. Declare responseData: null and check
<div class="profile-container" v-if=" responseData !== null">
problem is here,
responseData.followers is not take place immediately when render. because api call response will take time. so replace that line like this way
<Follow
v-if="responseData.followers && responseData.followers.includes($store.state.userId)">
</Follow>
and may be you should call those api synchronously, but it is depending on your requirement. if there is any dependency between those two api then should call synchronously but any other case it is ok.
//asynchronous operation
created() {
this.getAPICall(this.APIUrl)
this.getSecondAPICall(`api/user-post-list/${this.$route.params.userId}`)
}
//synchronous operation
async created() {
await this.getAPICall(this.APIUrl)
await this.getSecondAPICall(`api/user-post-list/${this.$route.params.userId}`)
}
There is little change required in your code like followers: [] has set in your data() return
data() {
return {
list: [],
responseData: {followers: []},
responseData2: {},
APIUrl: `api/user/${this.$route.params.userId}`
}
},
I have this code
(Pay attention to the HTML class 'symbolTicket "')
<template>
<div class="chart">
<span class="symbolTicket">
{{getTicket()}}
</span>
<div class="chartContent">
</div>
<!-- <div class="chartContent"> end -->
</div>
<!-- <div class="chart"> end -->
</template>
<script>
import axios from 'axios';
export default{
data() {
return {
};
},
methods: {
getTicket: function () {
return axios.get("http://localhost:2000/" , {
params: {
foo: 'SELECT * FROM eur_usd WHERE primary_key = 2;'
}
})
.then(function (response) {
console.log(response.data.ticket);
return response.data.ticket;
})
.catch(function (error) {
console.log(error);
});
},
},
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
I need to somehow get the value out of the query.
P.S. The result of the current solution can be seen on the screen.
From the top you can see what value is returned. (Object instead of data)
From the bottom of the console log - we see that the answer itself is working (no errors.)
It is this data that needs to be displayed inside the tag.
The standard way to do this would be to display a data property in the template.
<span class="symbolTicket">
{{ ticket }}
</span>
data () {
return {
ticket: null
}
}
Then load the value from the created hook:
created () {
this.getTicket()
},
methods: {
getTicket () {
return axios.get("http://localhost:2000/" , {
params: {
foo: 'SELECT * FROM eur_usd WHERE primary_key = 2;'
}
})
.then(response => {
const ticket = response.data.ticket;
// Update the data property
this.ticket = ticket;
console.log(ticket);
return ticket;
})
.catch(function (error) {
console.log(error);
});
}
}
The method getTicket is making an asynchronous request to the server so there's no way it can return the ticket directly. All it can return is the corresponding promise. The template needs the value synchronously, so relying on the return value from getTicket can't work.
You may also need to handle the case where ticket is null. During the initial rendering the request to the server won't have completed, so ticket will still be null.
If you're happy using async/await the getTicket method can be simplified but it won't change the overall flow described above. You still need a separate data property to hold the result.
Hi friends i am using laravel 5.6 with vue.js for crud function . I want to get the posts which i just posted in posts section without reloading the whole page again. I have written this code but these codes are sending the data to the console but not to the posts view section .
My app.js looks like this
const app = new Vue({
el: '#app',
data: {
msg: 'Update new Post:',
content:'',
posts:[]
},
ready:function(){
this.created();
},
created(){
axios.get('http://{mylink}/home/post')
.then(response=>{
console.log(response.data);//show if success
this.posts = response.data; // putting posts into array
})
.catch(function (error) {
console.log(error.response);
});
},
methods:{
addPost(){
axios.post('http://{mylink}/home/addPost', {
content:this.content
})
.then(function(response){
console.log('Data updated');
if (response.status == 200) {
alert('Your post has been updated');
app.posts=reponse.data;
}
})
.catch(function(error){
console.log(error.response);
});
}
}
});
my controllers looks like this
public function posts(){
$posts=DB::table('posts')
->leftJoin('users','users.id','posts.user_id')
->leftJoin('profiles','profiles.user_id','posts.user_id')
->get();
return view('home',compact('posts'));
}
public function addPost(Request $request){
$content = $request->content;
$createPost=DB::table('posts')
->insert(['content'=>$content,'user_id'=>Auth::user()->id,
'status'=>0,'created_at'=>date("Y-m-d H:i:s"),'updated_at'=>date("Y-m-d H:i:s")]);
if($createPost){
$posts_json = DB::table('posts')
->leftJoin('users','users.id','posts.user_id')
->leftJoin('profiles','profiles.user_id','posts.user_id')
->orderBy('posts.created_at','DESC')->take(2)
->get();
return $posts_json;
}
}
Routes looks like this
Route::post('/home/addPost','PostController#addPost')->name('home.addPost');
Route::get('/home/post',function(){
$posts_json = DB::table('posts')
->leftJoin('users','users.id','posts.user_id')
->leftJoin('profiles','profiles.user_id','posts.user_id')
->orderBy('posts.created_at','DESC')
->get();
return $posts_json;
});
and my view looks like this
<div v-for="post in posts">
<div class="card">
<div class="card-body">
<blockquote class="blockquote mb-0">
<p>#{{post.content}}</p>
<footer class="blockquote-footer">Status By <cite title="Source Title">#{{post.name}}</cite> <img src="{{url('/')}}/img/" alt="Card image cap" height="30px" width="30px" style="border-radius:50%;"></footer>
</blockquote>
</div>
</div>
</div>
I see many problems to your code but if the problem is only in addPost (you said that there is the problem) method then replace it with the follow:
addPost(){
axios.post('http://{mylink}/home/addPost', {
content:this.content
})
.then(response => {
console.log(response.data);
if (response.status == 200) {
alert('Your post has been updated');
this.posts = reponse.data;
}
})
.catch(error =>{
console.log(error.response);
});
}
also if you replace your method with the method that i posted you will be able to see what response you get from backend since i console logged it.Then you will see if you get a desired response
As noted in your comments above, this is an issue with authorization. I'll leave my old answer here for posterity, but including the status code from the start of the question would be good next time.
I believe your 'this' context is invalid when used inside the callback like that. Try something like this (edit) just realized you wanted the addPosts section:
addPost(){
let vm = this;
axios.post('http://{mylink}/home/addPost', {
content:this.content
})
.then(function(response){
console.log('Data updated');
if (response.status == 200) {
alert('Your post has been updated');
vm.posts=reponse.data;
}
})
.catch(function(error){
console.log(error.response);
});
}
Running into a snag with trying to integrate my API with Vue/Axios. Basically, Axios is getting the data (it DOES console.log what I want)... But when I try to get that data to my empty variable (in the data object of my component) to store it, it throws an "undefined at eval" error. Any ideas on why this isn't working for me? Thanks!
<template>
<div class="wallet-container">
<h1 class="title">{{ title }}</h1>
<div class="row">
{{ thoughtWallet }}
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'ThoughtWallet',
data () {
return {
title: 'My ThoughtWallet',
thoughtWallet: [],
}
},
created: function() {
this.loadThoughtWallet();
},
methods: {
loadThoughtWallet: function() {
this.thoughtWallet[0] = 'Loading...',
axios.get('http://localhost:3000/api/thoughts').then(function(response) {
console.log(response.data); // DISPLAYS THE DATA I WANT
this.thoughtWallet = response.data; // THROWS TYPE ERROR: Cannot set property 'thoughtWallet' of undefined at eval
}).catch(function(error) {
console.log(error);
});
}
}
}
</script>
Because you're using .then(function(..) { }) this won't refer to the vue context this.
You have two solutions, one is to set a variable that references the this you want before the axios call, e.g.:
var that = this.thoughtWallet
axios.get('http://localhost:3000/api/thoughts').then(function(response) {
console.log(response.data); // DISPLAYS THE DATA I WANT
that = response.data; // THROWS TYPE ERROR: Cannot set property 'thoughtWallet' of undefined at eval
}).catch(function(error) {
console.log(error);
});
The other is to use the new syntax (for which you need to make sure your code is transpiled correctly for browsers that don't support it yet), which allows you to access this inside the scoped body of the axios then.
axios.get('http://localhost:3000/api/thoughts').then((response) => {
console.log(response.data); // DISPLAYS THE DATA I WANT
this.thoughtWallet = response.data; // THROWS TYPE ERROR: Cannot set property 'thoughtWallet' of undefined at eval
}).catch(function(error) {
console.log(error);
});
The reason this happens is because inside that function/then, this will be referring to the context of the function, hence there won't be a thoughtWallet property
this.thoughtWallet inside the .get method is referring to the axios object, not Vue's. You can simply define Vue's this on the start:
methods: {
loadThoughtWallet: function() {
let self = this;
this.thoughtWallet[0] = 'Loading...',
axios.get('http://localhost:3000/api/thoughts').then(function(response) {
console.log(response.data); // DISPLAYS THE DATA I WANT
self.thoughtWallet = response.data;
}).catch(function(error) {
console.log(error);
});
}
}
I am working on a project to pull in twitter timeline's for selected teams/players. When I am on the team/_id page, how can I grab an attribute to path through a method?
Below is my client side javascript, as well as the relevant route from iron router. When I type in something like "patriots" to the "????" section, I get a result. I would like to do this dynamically, I currently have the twitter handles stored under the twitter attribute.
Template.tweets.helpers({
teams: function() {
return Teams.find();
},
});
Template.tweets.onRendered(function () {
var twitterHandle = "???";
Meteor.call('getTimeline', twitterHandle, function(err,results){
if (err) {
console.log("error", error);
};
console.log(results);
Session.set("twitter", JSON.parse(results.content));
})
return Session.get("twitter");
});
Router.route('/teams/:_id', {
name: 'teamView',
template: 'teamView',
data: function(){
var currentTeam = this.params._id;
return Teams.findOne({ _id: currentTeam });
var twitterHandle = this.params.twitter;
return Teams.findOne({twitter: twitterHandle});
}
});
<template name="tweets">
<h3>Tweets</h3>
<div class="container">
{{twitter}}
</div>
</template>
You should be able to access all information from the current route using the Router.current() object. In your case you can use Router.current().params._id to get the _id param:
var twitterHandle = Router.current().params._id;
Edits based on your comments below
I did not notice that you were calling the Teams.findOne function twice in your route's data function. Form the looks of it you're already storing the twitter handle in the Teams collection, so you merely need to access the data that's returned by the route.
Template.tweets.helpers({
twitterData: function() {
//return the data stored in the callback function of the Meteor method call in the onRendered event
return Session.get('twitter');
}
});
Template.tweets.onRendered(function () {
//clear any previously stored data making the call
Session.set('twitter', null);
//property of the team document returned by the data function in the route.
var twitterHandle = this.data.twitter;
Meteor.call('getTimeline', twitterHandle, function(err,results){
if (err) {
console.log("error", error);
} else {
Session.set("twitter", JSON.parse(results.content));
}
});
});
Router.route('/teams/:_id', {
name: 'teamView',
template: 'teamView',
data: function(){
var currentTeam = this.params._id;
return Teams.findOne({ _id: currentTeam });
}
});
<template name="tweets">
<h3>Tweets</h3>
<div class="container">
<!-- twitterData will be an object, so you'll need to figure out what properties to display and use dot notation//-->
{{twitterData}}
</div>
</template>