Vue.js doesn't display calendars - javascript

I am using vue-full-calendar to display calendars on my webpage.
Here i iterate through my projects in my database and get the dates so i can fill the calendar events later (using props in my-message component).
<template>
<div class="row" >
<div #click="clickedDiv" v-for="val in allProjects" :key="val.projectName" class="col-md-5 margin-bottom-30" >
<my-message id ="calendar" v-bind:title="val.projectName" v-bind:dates= val.answeredDates v-bind:dateTitle = val.projectId v-bind:link="'/#/editstartup' + '?id=' + val.projectId + '&title='+ val.projectName "></my-message>
</div>
</div>
</template>
The my-message component is inside main class :*
Vue.component('my-message', {
props: ['dates', 'title', 'dateTitle', 'link'],
data: function () {
var customEvents = [];
this.dates.forEach((event) => {
customEvents.push({
title: this.dateTitle,
start: event,
color: 'rgb(0, 95, 206)',
textColor: 'rgb(0, 95, 206)',
clickedDate: '',
projectId: '',
answeredDateConfirmURI: 'http://...'
})
})
return {
isVisible: true,
events: customEvents,
config: {
defaultView: 'month',
},
}
},
methods: {
getAnsweredDateConfirm: function (id) {
axios.get('http://localhost:8081/webapi/projects/answers/' + id)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
},
eventRender: function (event, element) {
// console.log(event)
},
eventClick: (event) => {
this.selected = event;
console.log(event);
this.projectId = event.title;
this.clickedDate = event.start._i;
this.$router.push("mystartups?date=" + this.clickedDate + "&project_id=" + this.projectId + "&project_title=" + this.title);
},
dayClick(date, event, view) {
// console.log(date, event, view)
console.log(date.format())
console.log(event);
},
refreshEvents() {
this.$refs.calendar.$emit('refetch-events')
},
eventSelected(event) {
this.selected = event;
console.log(event);
}
},
template: `
<article class="tile is-child notification" v-show="isVisible">
<!--
<p class="title">{{ title }}</p>-->
<a class="title" v-bind:href=link style="text-decoration:none; font-family: 'Open Sans', sans-serif;"> {{title}}
<i class="far fa-edit"></i>
</a>
<button class="delete" aria-label="delete" #click="isVisible = false"></button>
<full-calendar ref="calendar" :config="config" :events="events" #event-selected="eventSelected"></full-calendar>
<p class="subtitle">{{ body }}</p>
</article>
`
});
This code works when i use it locally, but when i build it, the calendats don't show and i get this error :
> vue.esm.js:1741 ReferenceError: body is not defined
> at o.eval (eval at ko (vue.esm.js:10680), <anonymous>:3:642)
> at o.t._render (vue.esm.js:4544)
> at o.<anonymous> (vue.esm.js:2788)
> at je.get (vue.esm.js:3142)
> at new je (vue.esm.js:3131)
> at vue.esm.js:2795
> at o.hn.$mount (vue.esm.js:8540)
> at o.hn.$mount (vue.esm.js:10939)
> at init (vue.esm.js:4137)
> at vue.esm.js:5608

Related

Error when sending dropzone images to laravel backend

So I have a dropzone file uploader. each successfull upload returns the following
File: {
"upload": {
"uuid": "f89f409b-7e49-4503-98d8-dc060e75b874",
"progress": 0,
"total": 5017004,
"bytesSent": 0,
"filename": "20190902_115950.jpg"
},
"status": "error",
"previewElement": {},
"previewTemplate": {},
"accepted": false,
"dataURL": "data:image/jpeg;base64,/9j/4XGiRXh/WU8GGXVL5BHN5PW...",
"width": 3024,
"height": 4032
}
I have a laravel backend with a request validation for this:
rules = [
...
'featured_image' => 'image',
]
However, my laravel backend returns that the featured image field must be an image. So I'm not sure what format the backend expects.
My dropzone component looks like this:
<template>
<div
class="dropzone mb-3 dz-clickable"
:class="[multiple ? 'dropzone-multiple' : 'dropzone-single']"
>
<div class="fallback">
<div class="custom-file">
<input
type="file"
class="custom-file-input"
id="projectCoverUploads"
:multiple="multiple"
/>
<label class="custom-file-label" for="projectCoverUploads"
>Choose file</label
>
</div>
</div>
<div
class="dz-preview dz-preview-single"
v-if="!multiple"
:class="previewClasses"
ref="previewSingle"
>
<div class="dz-preview-cover">
<img class="dz-preview-img" data-dz-thumbnail />
</div>
</div>
<ul
v-else
class="dz-preview dz-preview-multiple list-group list-group-lg list-group-flush"
:class="previewClasses"
ref="previewMultiple"
>
<li class="list-group-item px-0">
<div class="row align-items-center">
<div class="col-auto">
<div class="avatar">
<img class="avatar-img rounded" data-dz-thumbnail />
</div>
</div>
<div class="col ml--3">
<h4 class="mb-1" data-dz-name>...</h4>
<p class="small text-muted mb-0" data-dz-size>...</p>
</div>
<div class="col-auto">
<button data-dz-remove="true" class="btn btn-danger btn-sm">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "dropzone-file-upload",
props: {
options: {
type: Object,
default: () => ({}),
},
value: [String, Object, Array],
url: {
type: String,
default: "http://",
},
multiple: Boolean,
previewClasses: [String, Object, Array],
},
model: {
prop: "value",
event: "change",
},
data() {
return {
currentFile: null,
files: [],
showList: false,
};
},
methods: {
async initDropzone() {
let Dropzone = await import("dropzone");
Dropzone = Dropzone.default || Dropzone;
Dropzone.autoDiscover = false;
let preview = this.multiple
? this.$refs.previewMultiple
: this.$refs.previewSingle;
let self = this;
let finalOptions = {
...this.options,
url: this.url,
thumbnailWidth: null,
thumbnailHeight: null,
previewsContainer: preview,
previewTemplate: preview.innerHTML,
maxFiles: !this.multiple ? 1 : null,
acceptedFiles: !this.multiple ? "image/*" : null,
init: function () {
this.on("addedfile", function (file) {
if (!self.multiple && self.currentFile) {
// this.removeFile(this.currentFile);
}
self.currentFile = file;
});
},
};
this.dropzone = new Dropzone(this.$el, finalOptions);
preview.innerHTML = "";
let evtList = [
"drop",
"dragstart",
"dragend",
"dragenter",
"dragover",
"addedfile",
"removedfile",
"thumbnail",
"error",
"processing",
"uploadprogress",
"sending",
"success",
"complete",
"canceled",
"maxfilesreached",
"maxfilesexceeded",
"processingmultiple",
"sendingmultiple",
"successmultiple",
"completemultiple",
"canceledmultiple",
"totaluploadprogress",
"reset",
"queuecomplete",
];
evtList.forEach((evt) => {
this.dropzone.on(evt, (data) => {
this.$emit(evt, data);
if (evt === "addedfile") {
this.files.push(data);
this.$emit("change", this.files);
} else if (evt === "removedfile") {
let index = this.files.findIndex(
(f) => f.upload.uuid === data.upload.uuid
);
if (index !== -1) {
this.files.splice(index, 1);
}
this.$emit("change", this.files);
}
});
});
},
},
async mounted() {
this.initDropzone();
},
};
</script>
<style></style>

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.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() {},
});

Passing axios data to view template

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>

Vue not updating

I'm new to Vue js - the following is not updating:
<div id="error" class="col s12 red center">
<span v-if="seen">
Error fetching readings: {{ msg }}
</span>
</div>
Vue:
var error = new Vue({
el: '#error',
data: {
msg: '',
seen: false
},
methods: {
show: function(message) {
this.msg = message;
this.seen = true;
},
hide: function() {
this.seen = false;
}
}
});
Post fetch:
fetch( ... )
.then(...)
.catch(err => {
error.show( err );
loader.hide();
});
error.show() displays the previously hidden div, but displays:
Error fetching readings: {}
Why?
i created a CodeSandbox sample based upon your code, you need to have computed property to have the Vue reactivity
Sample can be found, check code in HelloWorld.vue in components folder
https://codesandbox.io/s/x2klzr59wo
<template>
<div id="error" class="col s12 red center">
{{ seen }}
<hr />
<span v-if="computedSeen"> Error fetching readings: {{ msg }} </span>
<hr />
<button #click="show('effe');">SHOW</button>
<button #click="hide();">HIDE</button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
msg: "",
seen: false
};
},
methods: {
show: function(message) {
this.msg = message;
this.seen = true;
},
hide: function() {
this.seen = false;
}
},
computed: {
computedSeen: function() {
// `this` points to the vm instance
return this.seen;
}
}
};
</script>
Oops, problem was err from the fetch is an object, and I should have used err.message.
In my code I had a console.log('Error: %s', err) which appears to format the err object into text. Which is what threw me :(
Sorry.

Categories