Passing axios data to view template - javascript

I am creating a simple SPA using vue.js and axioz as a scripts (not cli, etc)
So far I am able to pull data from a json then render and paginate the list,and when an item is clicked I am able to console log the data for the specific entry.
HTML
<!--app-->
<div id="app">
<!--articles-->
<div class="row" style="background: #111; padding: 8em 0; width: 50%;">
<div class="ctr">
<div class="row articles page_content" style="padding: 0;">
<ul>
<li v-for="(post) in displayedPosts" #click="getSingle(post.id)">
<router-link :to="{ path: '/post/'+ post.id}" class="flex" >
<div class="row article_thumb">
<img :src="post.url" :alt="post.title"/>
</div>
<div class="row article_excerpt">
<h3 class="title">{{post.title }}</h3>
</div>
</router-link>
</li>
</ul>
</div>
<div class="row pagination">
<button type="button" v-if="page != 1" #click="page--"> << </button>
<button type="button" v-for="pageNumber in pages.slice(page-1, page+5)" #click="page = pageNumber"> {{pageNumber}} </button>
<button type="button" #click="page++" v-if="page < pages.length"> >> </button>
</div>
</div>
</div>
<!--articles-->
<div class="row" style="background: #000; padding: 8em 0; width: 50%;">
<div class="flex router">
<router-view></router-view>
</div>
</div>
</div>
<!--app-->
VUE.JS
const Home = {
template: "<div><h1>Click an article to update this view</h1></div>"
};
//post
var Post = {
template:
'<div class="row"><h1>Display data for Post ID # {{$route.params.id}} here</h1><p style="color: red;">This is where I am stuck, cant display the post data, see example below.</p><p>{{title}}</p></div>',
//post methods
methods: {
//get single post
getSingle: function(id) {
var self = this;
this.id = this.$route.params.id;
this.title = this.title;
axios
.get(this.baseUrl, {
params: {
id: this.id,
}
})
.then(response => {
this.post = response.data;
this.title = response.data.title;
console.log(this.title);
console.log(this.post);
console.log("You clicked post ID #" + this.id);
})
.catch(response => {
console.log(error);
});
}
},
//post methods
//post data
data() {
return {
baseUrl: "https://jsonplaceholder.typicode.com/photos",
posts: [],
title: this.title
};
},
//post created
created() {
this.getSingle(this.$route.params.id);
},
watch: {
"$route.params": {
handler(newValue) {
const { id } = newValue;
this.getSingle(id);
},
immediate: true
}
}
};
//post
//router
const router = new VueRouter({
routes: [
{ path: "/", component: Home },
{ path: "/post/:id", component: Post }
]
});
//initial state
var paginationApp = new Vue({
el: "#app",
router: router,
data: {
posts: [],
baseUrl: "https://jsonplaceholder.typicode.com/photos",
page: 1,
perPage: 2,
pages: []
},
//initial state methods
methods: {
//get single
getSingle() {},
//get posts
getPosts() {
axios
.get(this.baseUrl)
.then(response => {
this.posts = response.data;
})
.catch(response => {
console.log(response);
});
},
//set pages
setPages() {
let numberOfPages = Math.ceil(this.posts.length / this.perPage);
for (let index = 1; index <= numberOfPages; index++) {
this.pages.push(index);
}
},
//paginate
paginate(posts) {
let page = this.page;
let perPage = this.perPage;
let from = page * perPage - perPage;
let to = page * perPage;
return posts.slice(from, to);
}
},
//created
created() {
this.getPosts();
},
//watch
watch: {
posts() {
this.setPages();
}
},
//computed
computed: {
displayedPosts() {
return this.paginate(this.posts);
}
}
});
//initial state
Or see this codepen for full example https://codepen.io/flashvenom/pen/YozyMx and be sure to checkout the console log.
My problem is i cannot console log the title or any internal fields of the data object, as I want to be able to add the title etc into the view area.
Any help or pointers would be much appreciated.

The response is in array form and you cannot access array object element without looping array.
If you wish to get title of first post, then you can do as shown below,
this.title = response.data[0].title
To access all posts title, you can use v-for loop in you vue template. Here is little example on how you can accomplish that,
<div v-for="post in posts">
<span>{{ post.title }}</span>
</div>

Related

Trying to compare a string value from database(firestore) to a inputted string from a text field. im using vue framework

<template>
<div id="profile" class="collection with-header">
<div class="profview">
</div>
<div class="search blue">
<div class="input-field">
<div class="input-field">
<i class="material-icons prefix"></i>
<input type="text" id="usernames" v-model="usernames" />
<label class="white-text" for="email">Enter username</label>
</div>
<button
v-on:click="followlist"
class="btn btn-large btn-extended grey lighten-4 black-text"
>
Search
</button>
</div>
</div>
<div class="list right red">
{{ word }}
<li v-for="user in users" v-bind:key="user.id" class="collection-item">
<button v-on:click="followlist">{{user.name}}</button>
<!--<button v-on:click="seeoptions = !seeoptions">{{user.name}}</button>-->
<div id="options" v-if="seeoptions">
<li><button>Follow</button></li>
<li><button>Block</button></li>
<li><button>View Profile</button></li>
</div>
</li>
</div>
</div>
</template>
<style>
template{
background-color: blueviolet
}
</style>
<script>
//lets see if we can implement the search function using login as
// a template, change data to match with what u need
import db from './firebaseInit'
import firebase from "firebase";
var auth = firebase.auth();
var exists = false;
export default {
name: "followlist",
data: function () {
return {
users: [],
loading: true,
usernames: "",
word: 'This is a friends list',
content: 'Info of User',
content2: 'A search bar',
//seeoptions1: false,
// seeoptions2: false,
//seeoptions3: false
}
},
methods:{
followlist: function(e) {
db.collection('users').get().then((querySnapshot) =>{
this.loading = false
//console.log("succes");
//let inputtedname = document.getElementById("username").value;
//let stringName = inputtedname.toString()
querySnapshot.forEach((doc) => {
// console.log("succes");
// console.log(stringName);
var tempname = this.usernames;
var temp = doc.data().username;
// console.log(this.username);
// console.log(temp);
var curruser = this.username;
if(tempname == temp){
console.log(doc.data().username)
}
else
console.log("dont know")
})
// console.log(stringName)
})
},
},
created () {
// Boolean userExists = false;
db.collection('users').orderBy('dept').get().then((querySnapshot) => {
this.loading = false
querySnapshot.forEach((doc) => {
const data = {
'id': doc.id,
'name': doc.data().name,
'dept': doc.data().dept,
//'position': doc.data().position
}
this.users.push(data)
})
})
}
}
</script>
ignore all the commented out console logs, anyways, i tried setting both to a variable, i tried doing it by straight comparing this.username to the one in database. its getting the username from the database correctly, ive console logged it and it worked fine, outputted all the usernames from database. however at the if statement, it will not compare them correctly if they are matches. also ignore the bottom created () section, its nnot doing anything currently. just was used to test
Its probably due to a space in one of the string.
if(tempname.trim() == temp.trim()) {
console.log(doc.data().username)
}

I can't show the meteorological icon

I am creating a time application using the Openweather API. I try to show the meteorological icon corresponding to the selected city and the meteorological state.
My code is as follows:
HTML:
<div class="column">
<div class="media-content">
<div class="content">
<p>
<strong>
<h1 class="has-text-inf o"> {{ ciutatActual.weather[0].icon }} </h1>
</strong>
</p>
</div>
</div>
</div>
javascript:
var vm = new Vue({
el: '#eltemps',
data: {
selectedCity: "",
ciutatActual: null,
ciutats: [
"Barcelona",
"Lleida",
"Zaragoza",
"Sevilla",
"Madrid",
"Paris",
"Melbourne",
"Moscow",
"Pekin",
"Marrakech"]
},
created: function () {
this.selectedCity = this.ciutats[0]
},
watch: {
selectedCity: function (){
this.getWeather(this.selectedCity)
}
},
methods: {
getWeather(city) {
const url = 'https://api.openweathermap.org/data/2.5/weather?q=' + city + '&units=metric&lang=ca&appid=8660dddfbe5f16ee37dbd6883d8f07d5';
fetch(url)
.then(function (response) {
return response.json()
})
.then(function (item) {
vm.ciutatActual = item;
})
.catch(function(error) {
console.log(error);
})
},
itemClicked: function(item) {
this.getWeather();
this.onClick(item);
}
}
})
The ruling comes from here: {{ciutatactual.weather [0] .icon}}
that instead of showing the icon it shows me just one code

Vue method not passing data to array of objects

So I'm going to be explaining this in the best way possible as I don't understand what might be causing this issue on my end as I feel like I've followed all of the directions and keep hitting a brick wall.
Here is my vue.js app:
new Vue({
name: 'o365-edit-modal-wrapper',
el: '#o365-modal-edit-wrapper',
data: function() {
const default_apps = [
{
'post_title': 'Excel',
}, {
'post_title': 'Word',
}, {
'post_title': 'SharePoint',
}];
console.log(default_apps);
const default_apps1 = this.get_array_of_post_objects('application_launcher');
console.log(default_apps1);
return {
available_list: [],
selected_list: default_apps.map(function(name, index) {
return {
name: name.post_title,
order: index + 1,
fixed: false
};
}),
}
},
methods: {
get_array_of_post_objects(slug) {
let items = [];
wp.api.loadPromise.done(function () {
const Posts = wp.api.models.Post.extend({
url: wpApiSettings.root + 'menus/v1/locations/' + slug,
});
const all_posts = new Posts();
all_posts.fetch().then((posts) => {
items.push(...posts.items);
});
});
return items;
},
},
computed: {
dragOptions() {
// Pass in additional <draggable> options inside the return for both lists.
return {
tag: 'div',
group: 'o365apps',
disabled: !this.editable,
ghostClass: "ghost",
};
},
},
});
Inside my methods, I have a method called get_array_of_post_objects which returns an array of objects that I'm pulling through.
So inside data, I'm console logging my manual default_apps and my default_apps1 which is the method. Both of the arrays of objects have post_title: "something" inside.
Here is the return that I'm getting:
Inside my mapping, when I define default_apps, my IDE returns some result for name but when I switch it over to default_apps1, it's not finding any results as shown below:
I don't know what else to look at - All help would be appreciated!
Here is the HTML code if that is needed:
<div class="column is-half-desktop is-full-mobile buttons">
<nav class="level is-mobile mb-0">
<div class="level-left">
<div class="level-item is-size-5 has-text-left">Selected</div>
</div>
<div class="level-right">
<div class="level-item" #click="orderList()"><i class="fas fa-sort-alpha-up is-clickable"></i></div>
</div>
</nav>
<hr class="mt-1 mb-3">
<!-- Decorator: # also known as v-on: -->
<!-- Bind: : also known as v-bind: -->
<draggable class="list-group"
v-model="selected_list"
v-bind="dragOptions"
:move="onMove"
#add="onAdd"
#remove="onRemove"
#start="isDragging=true"
#end="isDragging=false">
<button class="button is-fullwidth is-flex list-group-item o365_app_handle level is-mobile" v-for="(app, index) in selected_list" :key="app.order">
<div class="level-left">
<span class="icon" aria-hidden="true">
<img :src="`<?= Path::o365('${app.name}' . '.svg'); ?>'`" />
</span>
<span>{{app.name}}</span>
</div>
<div class="level-right is-hidden-desktop">
<span class="icon has-text-danger is-clickable" #click="remove(index)">
<i class="fas fa-times"></i>
</span>
</div>
</button>
</draggable>
</div>
I'm not 100% sure what your app is supposed to do, so modify it for your needs.
Here the selected_list will be empty first.
Then we call your method, which is asynchronous, and once it's done selected_list gets populated.
new Vue({
name: 'o365-edit-modal-wrapper',
el: '#o365-modal-edit-wrapper',
data: function() {
return {
available_list: [],
selected_list: [],
}
},
created() {
this.get_array_of_post_objects("add-your-slug")
},
methods: {
get_array_of_post_objects(slug) {
wp.api.loadPromise.done(function() {
const Posts = wp.api.models.Post.extend({
url: wpApiSettings.root + 'menus/v1/locations/' + slug,
});
const all_posts = new Posts();
all_posts.fetch().then((posts) => {
// You might want to modify posts for your needs
this.selectedList = posts
});
});
},
},
});

Vue.js + Firebase update chat message box after sending

I'm starting with vue.js and firebase and I have a chat system using firebase. I get all the users’ id that have sent messages to me. So in my database I get their data and list with a v-for.
After listing them I get their messages from FB to list in a message box below each user.
Everything is working fine but I cannot get sent messages instantly after sending them.
I made a workaround with push() to append each sent message to data property but I'd like to know if there is a better way to do that with vue.js.
I've tested with plain javascript (separately with one message box) and the chat is updated on every sent message.
Is there a way to make this work without replacing all data object or calling all the listing process again? I tried with Vue's Reactivity but I could not make it work as expected.
<div v-if="isLoading == true" id="loading"><img class="loading" src="../assets/img/loading.gif" /></div>
<div v-if="isLoading == false" class="row messages-row" v-for="(item, index) in memberData" :key="index">
<div class="col-md-4 col-12">
<div class="messages-profile-infos">
<div class="messages-profile-infos-img img-fluid" v-bind:style="{'background-image': 'url(http://localhost/backend/imgs/'+item.memberProfileImg + ')' }"></div>
<div class="messages-profile-infos-text">
<p>{{ item.memberName }} {{ item.memberLastname }}</p>
<p>{{ item.memberCity }} - {{ item.memberState }}</p>
</div>
</div>
</div>
<div class="col-md-2 col-12">
<div class="messages-btns">
<button class="btn trade-btn" #click="showConversation(item.memberID)">Messages</button>
</div>
</div>
<div class="col-md-6 col-12">
<div class="messages-status">
<a class="btn border btn-circle text-uppercase confirm-service-btn" href="javascript:void(0);">
Confirm
</a>
<a class="btn border btn-circle text-uppercase cancel-service-btn" href="javascript:void(0);">Cancel</a>
</div>
</div>
<!-- conversation box -->
<div v-if="memberBox == item.memberID" class="conversation-container" :id="item.memberID">
<div v-for="(tour, index) in item.tours" :key="index" id="tourOnConversation" class="tourOnConversation">
<span>Tour:</span>
<span><strong>{{ tour.title }}</strong></span>
</div>
<div id="messages-container" class="messages-container" :key="item.memberID">
<div v-for="message in item.messages" class="d-flex" :class="[message.uid != myID ?'justify-content-start':'justify-content-end']">
<span class="badge badge-pill" :class="[message.uid != myID ?'badge-primary':'badge-secondary']">{{ message.message }}</span>
</div>
</div>
<div class="message-typing-container">
<form id="messages_form" action="" method="POST">
<div class="typing-container">
<input id="message" v-model="messages" type="text" class="message-typing" autocomplete="off" />
<input class="send-message" type="submit" value="Send" #click="sendMessage(item.memberID, item.tour)" />
</div>
</form>
</div>
</div>
<hr />
</div>
var firebaseConfig = {
apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxx",
authDomain: "xxxxxxxxxxxxxxxxxxxxx",
databaseURL: "xxxxxxxxxxxxxxxxxxxxx",
projectId: "xxxxxxxxxxxxx",
storageBucket: "xxxxxxxxxxxxxxxxxxx",
messagingSenderId: "xxxxxxxxxxxxx",
appId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
};
firebase.initializeApp(firebaseConfig);
let app = new Vue({
el: "#app",
data() {
return {
memberData: {},
myMessages: [],
memberMessages: [],
myID: userID,
messages: "",
messageBox: 0,
conversation: {},
isLoading: true,
memberBox: 0,
};
},
created: function () {
this.getAllMessages();
},
methods: {
scrollBox: function () {
let messagebox = document.querySelector("#messages-container");
messagebox.scrollTop = messagebox.scrollHeight;
},
getAllMessages: function () {
let distinct = "";
firebase
.firestore()
.collection("messages")
.where("memberID", "==", `${this.myID}`)
.orderBy("date")
.onSnapshot((res) => {
let members = [];
res.forEach((doc) => {
members.push(doc.data().uid);
});
distinct = Array.from(new Set(members));
this.getUserToTalk(distinct);
});
},
getMyMessages: function (memberID) {
let myMessages = [];
firebase
.firestore()
.collection("messages")
.where("uid", "==", `${this.myID}`)
.where("memberID", "==", `${memberID}`)
.orderBy("date")
.onSnapshot((res) => {
res.forEach((doc) => {
myMessages.push(doc.data());
});
});
return myMessages;
},
getMessages: function (memberID) {
let messages = [];
firebase
.firestore()
.collection("messages")
.where("uid", "==", `${memberID}`)
.where("memberID", "==", `${this.myID}`)
.orderBy("date")
.onSnapshot((res) => {
res.forEach((doc) => {
messages.push(doc.data());
});
});
return messages;
},
getUserToTalk: function (memberID) {
axios
.post("http://localhost/backend/getMemberToTalk.php", {
token: token,
whoToTalkTo: memberID,
})
.then((response) => {
// console.log(response.data);
if (response.data != "Error receiving data") {
let joinedData = [];
response.data.forEach((res) => {
let messages = this.getMessages(res.memberID);
let myMessages = this.getMyMessages(res.memberID);
// console.log(messages);
// console.log(myMessages);
let conversation = [];
let data = {};
setTimeout(() => {
conversation = [...messages, ...myMessages];
conversation.sort(function (a, b) {
return a.date - b.date;
});
// console.log(conversation);
if (conversation.length > 0) {
data = {
memberID: res.memberID,
memberProfileImg: res.memberProfileImg,
memberName: res.memberName,
memberLastname: res.memberLastname,
memberCity: res.memberCity,
memberState: res.memberState,
messages: conversation,
tour: conversation[0].tour,
};
this.isLoading = false;
} else {
this.isLoading = true;
this.getAllMessages();
}
joinedData.push(data);
}, 2000);
});
// console.log(joinedData);
this.memberData = joinedData;
console.log(this.memberData);
} else {
console.log(response.data);
}
})
.catch((error) => {
console.log(error);
});
},
sendMessage: function (memberID, tourID) {
$("#messages_form").on("submit", (e) => {
e.preventDefault();
let message = this.messages;
if (!message.trim()) return;
let postmessage = {
uid: JSON.stringify(this.myID),
memberID: JSON.stringify(memberID),
message: message,
date: Date.now(),
tour: "2",
};
// console.log(message);
this.messages = "";
this.memberData.forEach((res) => {
console.log(res.messages);
if (memberID == res.memberID) res.messages.push(postmessage);
});
console.log(this.memberData);
firebase.firestore().collection('messages').add({
uid: JSON.stringify(this.myID),
memberID: JSON.stringify(memberID),
message: message,
date: Date.now(),
tour: tourID
}).then(res => {
// console.log('Message sent: ' + res.message);
}).catch(e => console.log(e));
});
},
showConversation: function (memberID) {
// console.log(memberID);
// let id = $('.conversation-container').attr('id');
this.memberBox = memberID;
if (this.memberBox == memberID) {
$(".conversation-container").toggle("fast");
}
},
},
mounted() {},
});

How to Re-bind / Refresh Dom after ajax call in vuejs2 (like $scope.$apply in angularjs)?

I am using vue.js 2 with webpack template. i am new to vue.js.
i want to bind DOM after data is received in ajax call.
here in my code contains v-for in which the response html is need to bind with v-html="tHtml[index]" every time after data is received from api call.
What can be used to re-bind or refresh view/DOM as we use $scope.$apply() in angularjs.
home.vue
<template>
<div class="row" id="home">
<h3 v-if="msg"><span class="label label-warning">{{msg}}</span></h3>
</div>
<div v-for="obj in tdata">
<div v-html="tHtml[$index]"></div>
</div>
</div>
</template>
<script>
import appService from '../service'
import bus from '../service/bus'
export default {
created() {
appService.checkAuth();
console.log("service appService val: "+appService.user.authenticated);
//called after vue has been created
bus.$on('eventBusWithTopic', (data) => { //fetch event bus on ready to get data
//alert("event fetched! "+data.user_id);
console.log("event fetched! "+data.user_id);
this.searchedTopic = data.topic;
this.user_id = data.user_id;
bus.$off('eventBusWithTopic'); //un-bind event after use
//check details
})
},
data() {
return {
searchedTopic: '',
user_id: '',
tdata: {},
tHtml: []
}
},
methods: {
getdata(){
console.log("dfd "+this.user_id);
appService.getdata(this, this.user_id, this.searchedTopic).success((res) => {
//console.log(" res: "+JSON.stringify(res));
this.tdata = res.data;
if(this.tdata.length > 0){
//**GET HTML** // <<--==--==--==
for(var i=0;i<this.tdata.length;i++){
this.getTemplate(this.tdata[i].id_str);
}
}
if(res.success == 0)
this.msg = res.message;
}).error((e) => console.log("error while getting data: "+JSON.stringify(e)))
},
getTemplate(id){
this.$http.get("https://uqkcgyy8wb.execute-api..*****../user/"+id+"/getHtml", (resp) => {
//return resp.data.html;
this.tHtml[this.tHtml.length] = resp.data.html;
console.log(this.tHtml);
}).error((e) => console.log("error while getting html: "+JSON.stringify(e)))
}
}
}
</script>

Categories