Vuejs data not showing properly on mounted - firebase

Im new in Vuejs. I started a project with Vue, Firebase and using Chart Js inside of it. Here is the details of problem.
If I give any value of sales_today in data() it shows properly on mounted where I use it by this.sales_today also works perfectly in template {{sales_today}}.
But into the Created I'm trying to change this.sales_today value by an output of firebase query. then the output shows perfectly into template {{sales_today}} but not working inside the mounted here
**data: [this.sales_today,30,60,10]**
Template
<template>
{{sales_today}}
</template>
Data
data(){
return{
sales_today:''
}
},
Mounted
mounted() {
data: {
datasets: [{
data: [this.sales_today,30,60,10],
}]
}
}
Created
created(){
let ref = db.collection('sales').where("sales_date", "==", moment().format('DD-MM-YYYY'))
.get()
.then(snapshot => {
var total = 0;
snapshot.forEach(doc => {
total += Number(doc.data().price)
})
this.sales_today = total
})
}
Here is the complete code
https://github.com/Shakilzaman87/pukucrm/blob/master/src/components/dashboard/Dashboard.vue

This should be on mounted(). I don't have the editor on comments and i will answer here.
let ref = db.collection('sales').where("sales_date", "==", moment().format('DD-MM-YYYY'))
.get()
.then(snapshot => {
var total = 0;
snapshot.forEach(doc => {
total += Number(doc.data().price)
})
this.sales_today = total;
var chart = this.$refs.chart;
var ctx = chart.getContext("2d");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels:this.labels,
datasets: [{
label: 'Sales of June',
data: [this.sales_today,30,60,10],
backgroundColor: [
'#ffffff'
],
borderColor: [
'#1976d2'
],
borderWidth: 3
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
},
});
})
P.S. check the console for errors

Related

Why aren't my data points getting placed in the corresponding locations in my chart?

I have a Nuxt component that loads a chart using chart.js, filled with data from a Firestore database. The data points are loading as a flat line at the bottom of my chart. However, the data has different value ranges when hovered.
How do I get the data points to render in the correct locations to produce an actual graph?
I've tried using a loaded variable to load the chart after the Firestore data is retrieved. I end up with the exact same issue.
I've tried adding some static weight array data before the data is pushed to it. When doing that, it showed those points accurately, but the rest laid flat on the bottom (still showing valid data point values on hover).
<template>
<div id="container">
<canvas ref="chart"></canvas>
</div>
</template>
<script>
import { firebase, db } from '#/plugins/firebase'
import Chart from 'chart.js'
const color = ['#3AC', '#D91D63', '#5F6982', '#F4B651', '#3F4952']
export default {
data() {
return {
laoded: false,
weightData: [],
}
},
async mounted() {
// retrieve weight data from firebase
this.getWeightData()
const ctx = this.$refs.chart
const chart = new Chart(ctx, {
type: 'line',
data: {
labels: ['January', 'February', 'March', 'April', 'May', 'June'],
datasets: [{
data: this.weightData,
backgroundColor: color[0],
borderColor: color[0],
borderWidth: 1,
fill: false,
label: 'weight',
responsive: true
}]
},
options: {
legend: {
usePointStyle: true
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
stepSize: 10
}
}]
},
tooltips: {
callbacks: {
afterBody(tooltip, dataset) {
let data = 'goal: goal here'
return data
}
}
}
}
})
},
methods: {
getWeightData() {
firebase.auth().onAuthStateChanged(async user => {
if (user) {
const data = await db.collection('users').doc(user.uid).collection('weight').get()
.then(querySnapshot => {
if (!querySnapshot.empty) {
querySnapshot.forEach(doc => {
this.weightData.push(doc.data().weight)
})
}
})
}
})
this.loaded = true
}
}
}
</script>
I expect a line graph with the data points from the weightData array. All I'm getting is a flat line with different values in the tooltips.
Also, the chart's range is 0 to 1, even though weightData values go up as far as 200.
getWeightData() populates weightData asynchronously, so you'd have to await the function call before proceeding with setting up the chart.
First, wrap getWeightData() in a Promise 1️⃣so that you could return the fetched weight data 2️⃣(instead of setting this.weightData inside the Promise):
methods: {
getWeightData() {
return new Promise((resolve, reject) => { /* 1 */
firebase.auth().onAuthStateChanged(user => {
if (user) {
db.collection('users')
.doc(user.uid)
.collection('weight')
.get()
.then(querySnapshot => {
const weightData = []
if (!querySnapshot.empty) {
querySnapshot.forEach(doc => {
weightData.push(doc.data().weight)
})
}
resolve(weightData) /* 2 */
})
.catch(reject)
} else {
reject()
}
})
})
}
}
Then in mounted(), store the awaited result of getWeightData() in this.weightData 3️⃣:
async mounted() {
this.weightData = await this.getWeightData() /* 3 */
/* now, setup chart with `this.weightData` */
}

Find one and update with async.eachseries updates the first element only

Below is my code to update values in my MongoDB using mongoose. It updates only the first item in the array but not the second one.
I want this code to update both the items.
router.post('/updateattendance', (req, res) => {
let attendaceColl = [
{roll_number: 9915,date: '2019-05-21',was_present: true},
{roll_number: 9904,date: '2019-05-21',was_present: true}
];
async.eachSeries(attendaceColl, (stdnt, done) => {
UserSubjectDetails.findOneAndUpdate(
{
roll_number: stdnt.roll_number
},
{
$push: {
'subject_details.attendance.doc' : [{
date: stdnt.date,
was_present: stdnt.was_present
}]
}
}, function(err, rsesult) {
console.log('did')
}, done);
}, function(err, res){
console.log(res)
});
});

How can I upload an image to firebase storage and add it to the database?

I'm new to Vuejs. I want to have a form using which you can add products. The product image goes to firebase storage but how do I associate that image with the exact product in the database?
I've already set up my form, and created two methods. saveProduct() to save the products to the database and onFilePicked() to listen for changes in the input field and target the image and upload that to storage.
import { fb, db } from '../firebaseinit'
export default {
name: 'addProduct',
data () {
return {
product_id: null,
name: null,
desc: null,
category: null,
brand: null,
image: null,
}
},
methods: {
saveProduct () {
db.collection('products').add({
product_id: this.product_id,
name: this.name,
desc: this.desc,
category: this.category,
brand: this.brand
})
.then(docRef => {
this.$router.push('/fsbo/produkten')
})
},
onFilePicked (event) {
let imageFile = event.target.files[0]
let storageRef = fb.storage().ref('products/' + imageFile.name)
storageRef.put(imageFile)
}
}
}
what about this, you can use the filename, your images are going to be served as somefireurl.com/{your_file_name} on your product collection you can have an image prop with the imageFile.name.
methods: {
saveProduct (image = null) {
let productRef = db.collection('products').doc(this.product_id)
const payload = {
product_id: this.product_id,
name: this.name,
desc: this.desc,
category: this.category,
brand: this.brand
}
if (image) payload['image'] = image
return productRef
.set(payload, {merge: true})
.then(docRef => {
this.$router.push('/fsbo/produkten')
})
},
onFilePicked (event) {
let imageFile = event.target.files[0]
let storageRef = fb.storage().ref('products/' + imageFile.name)
storageRef.put(imageFile)
return this.saveProduct(imageFile.name)
}
}
That should be enough to get you started, maybe you want to try a different combination, or maybe you dont want to call saveProduct the way I set it, it's up to your use case but the idea is the same. Hope this can help you
I fixed it myself. Here's my solution. I don't know if it's technically correct but it works for my use case.
methods: {
saveProduct () {
let imageFile
let imageFileName
let ext
let imageUrl
let key
let task
db.collection('products').add({
product_id: this.product_id,
name: this.name,
desc: this.desc,
category: this.category,
brand: this.brand
})
.then(docRef => {
key = docRef.id
this.$router.push('/fsbo/produkten')
return key
})
.then(key => {
if(this.image !== null) {
this.onFilePicked
imageFile = this.image
imageFileName = imageFile.name
ext = imageFileName.slice(imageFileName.lastIndexOf('.'))
}
let storageRef = fb.storage().ref('products/' + key + '.' + ext)
let uploadTask = storageRef.put(imageFile)
uploadTask.on('state_changed', (snapshot) => {}, (error) => {
// Handle unsuccessful uploads
}, () => {
uploadTask.snapshot.ref.getDownloadURL().then( (downloadURL) => {
db.collection('products').doc(key).update({ imageUrl: downloadURL})
});
});
})
},
onFilePicked (event) {
return this.image = event.target.files[0]
}
}

Add a number to a list item with DynamoDB

This is the DynamoDB table structure I'm working on:
{
"userId": "99999999-9999-9999-9999-999999999999",
"userProfile": {
"email": "myemail#gmail.com",
"firstName": "1234124",
"lastName": "123423",
},
"masterCards": [
{
"cardId": 101000000000001,
"cardImage": "logo.png",
"cardName": "VipCard1",
"cardWallet": "0xFDB17d12057b6Fe8c8c425D2DB88d8475674567"
},
{
"cardId": 102000000000002,
"cardImage": "logo.png",
"cardName": "VipCard2",
"cardWallet": "0xFDB17d12057b6Fe8c8c425D2DB88d8183454345"
},
{
"cardId": 103000000000003,
"cardImage": "logo.png",
"cardName": "VipCard3",
"cardWallet": "0xFDB17d12057b6Fe8c8c425D2DB88d8184345345"
}
],
}
I'm trying to increase the cardId field by one for the first list item with this Lambda function:
const dynamoDB = new AWS.DynamoDB({region: 'eu-central-1', apiVersion:'2012-08-10'});
const counterId="99999999-9999-9999-9999-999999999999"
const params = {
TableName:"FidelityCardsUsers",
Key: {"userId":{"S":counterId}},
UpdateExpression:"ADD #masterCards[0].#cardId :increment",
ExpressionAttributeNames:{
"#masterCards": "masterCards",
"#cardId": "cardId"
},
ExpressionAttributeValues:{":increment": {"N": "1"}}
}
dynamoDB.updateItem(params, function(err, data) {
if (err) {
console.log('error getting counter from DynamDB: ',err)
callback(err);
} else {
callback(null,data)
}
})
In return I get only a new top-level attribute named "mastercards[0].cardId[0]" with a value number set to 1.
I have tried to increment In an array and its work fine with AWS.DynamoDB.DocumentClient()
Example :
var AWS = require("aws-sdk");
var docClient = new AWS.DynamoDB.DocumentClient();
let params = {
TableName:'tableName',
Key: {
'venueId': 'VENUE_002'
},
UpdateExpression: "ADD #walk.#coordinates[0] :increment",
ExpressionAttributeNames: {
'#walk': 'walk',
'#coordinates': 'coordinates'
},
ExpressionAttributeValues: {
':increment': 1 // This is from the client
},
ReturnValues: 'UPDATED_NEW'
};
docClient.update(params, function (err, data) {
if (err) {
console.log('failure:updateShuttleDirection:failed');
console.log(err);
} else {
console.log('success:updateShuttleDirection:complete');
console.log(data);
}
});
Sample Data:
"walk": {
"coordinates": [
10,
20
],
"type": "Point"
},
I have tried to increment 10 to 11 and its work fine
Reading the doc here, it seems that:
the ADD action can only be used on top-level attributes, not nested
attributes.

how to get JSON data in from firebase, and then use it in angular 6, firebase return the data with value tag

I am using firebase functions to get data from db, this is how I am doing it,
exports.getTopPlayers = (request,response)=> {
SavePlayers(function(data,err){
if(err) console.log(err);
response.header('Access-Control-Allow-Origin', '*');
response.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
const dbRef = admin.database().ref().child('topplayers/-LISMykRqLrVcc7xrK60');
dbRef.on('value', snap => {
var dbPlayer = snap.val();
response.send(dbPlayer);
});
});
Then I am using it in my website built in angular 6
getTopPlayers() {
return this.http.get(this.topPlayerURL);
}
It the be data in the below format,
{value: "[{"name":"WHYALWAYSME","tag":"9P08LYLL","rank":1,"…na":"League 8","arenaID":20,"trophyLimit":6100}}]"}
I want to get rid of this value tag. How can I? When I try to loop on this using
ngFor (*ngFor="let tp of topPlayer$) it return error, Cannot loop
[object,object]
I want the data in the below format,
[
{
name: "Leslie",
tag: "RPP89PVY",
rank: 1,
previousRank: 3,
expLevel: 13,
trophies: 6361,
donationsDelta: null,
clan: {
tag: "9CU2PQ2J",
name: "不正经的养老院",
badge: {
name: "Cherry_Blossom_04",
category: "01_Symbol",
id: 16000131,
image: "https://royaleapi.github.io/cr-api-assets/badges/Cherry_Blossom_04.png"
}
},
arena: {
name: "Grand Champion",
arena: "League 8",
arenaID: 20,
trophyLimit: 6100
}
},
I found the solution,
In angular in component init method, I did the following,
Call the service and read the data in a string array,
topPlayer$: string[];
ngOnInit() {
this.topPlayerSrvice.getTopPlayers()
.subscribe(response => {
let topPlayer: string[];
topPlayer = response.json();
this.topPlayer$ = JSON.parse(topPlayer['value']);
});
}

Resources