Problem in Vue Express with displaying image - javascript

I'm developing an express vue app. I have a problem in displaying image in vue.
In a vue page, I run an axios.get in vue js beforeMount hook, and get images data in base64 from API.
Then save data in an array. I don't see images but texts haven't problem. In some page refreshes like editing code and ... I see images but then problem remain.
vue js code:
<template>
<div v-for="(designImg, i) in designImgs" :key="i">
<q-img
:src="designImg"
height="100px"
class="bg-grey-4"
/>
</div>
<template>
<script>
data () {
return {
designImgs: null
}
},
beforeMount () {
this.$axios.get('shop/product', {
params: {
designId: this.$route.params.designId,
}
}).then((res) => {
if (res.data.error) {
console.log(res.data.error)
} else {
const designImgUrls = res.data.imageUrls.split(',')
const mydesignImgs = []
for (let i = 0; i < designImgUrls.length; i++) {
this.$axios.get('/shop/image', {
params: {
url: designImgUrls[i]
}
}).then((res) => {
const url1 = 'data:image/jpeg;base64, ' + res.data
mydesignImgs[i] = url1
}).catch(err => {
console.log(err)
})
}
this.designImgs = mydesignImgs
}
}).catch((err) => {
console.log(err)
})
}
<script>
Note that in above code we recieve from server these data:
imageUrls: "uploads\imagee-1592862806606.jpg,uploads\imagee-1592862806654.jpg"
and then after getting images data res.data is equals to a base64 image data like this:
/9j/2wBDAAYEBQYFBAY...

I have solved this problem.
I have changed the way of collecting image data in mydesignImgs array.
i have used this code:
mydesignImgs.push(url1)
instead of using this equality:
mydesignImgs[i] = url1
but why?

Related

Framework7 + Vue + Firebase: Open an individual page displaying the dynamic info from the database?

How to I get to open a user with a dynamic url each to an individual page?
I use Framework7 + Vue for a Cordova Project.
I have customized the default product page that grabs an id and display data of a single product, It works by generating the unique ID (“uid” as per firebase) for each user in a url by it fails to pass it the user.vue page that I created, it doesn’t open when I click on it. What exactly could I be missing here? I don’t know much about JSON.stringify stuffs!
user.vue - the individual data page
<f7-page name="user">
<f7-navbar :title="user.username" back-link="Back"></f7-navbar>
<f7-block-title>About {{user.username}}</f7-block-title>
<f7-block strong>
{{user.email}}
</f7-block>
</f7-page>
<script>
export default {
data: function () {
var userId = this.$f7route.params.id;
var currentUser;
this.$f7.data.users.forEach(function (user) {
if (user.user_id === userId) {
currentUser = user;
}
});
return {
user: currentUser,
};
}
};
</script>
home.vue - the user list loop, working just fine as expected
<f7-list>
<f7-list-item
v-for="(user) in users"
:key="user.user_id"
:title="user.username"
:link="`/user/${user.user_id}/`"
></f7-list-item>
</f7-list>
home.vue - mounted functions script
mounted() {
let viewUsers = this;
const usersRef = firebase.database().ref("users");
usersRef.on("value", snapshot => {
let data = snapshot.val();
let users = [];
Object.keys(data).forEach(key => {
users.push({
id: key,
username: data[key].username,
user_email: data[key].email,
user_id: data[key].uid,
});
});
viewUsers.users = users;
});
}
home.vue - data returned script at the top
data() {
return {
users: this.$f7.data.users, //the arrays had already been called/initialized at the app.vue
}
routes.js:
import UserPage from ‘…/pages/user.vue’;
{
path: ‘/user/:id/’,
component: UserPage,
}
What exactly am i missing here?

FireBase dispatch function doesn't save to realtime DB

I need some help with a realtimeDB issue.Am using NuxtJS to store state and dispatch the state to DB.
My code is working fine regarding saving into to the DB. Whenever I want to edit it, I receive this 400 BAD Request error.
The same thing happens when i manually try to update info withing the Firebase realtime DB, I can't edit the line with the text.
ERROR:
vendor.js:387 PUT https://xxxx.firebaseio.com/posts.json-MI-Jym0mdX5jNNP89UH.json?auth=BIGKEY 400 (Bad Request)
My component
<template>
<div class="admin-post-page">
<section class="update-form">
<AdminPostForm :post="loadedPost" #submit="onSubmitted" />
</section>
</div>
</template>
<script>
import AdminPostForm from "#/components/Admin/AdminPostForm";
export default {
layout: "admin",
middleware: ['check-auth', 'auth'],
components: {
AdminPostForm
},
asyncData(context) {
return context.app.$axios
.$get(
process.env.baseUrl + "/posts/" +
context.params.postId +
".json"
)
.then(data => {
return {
loadedPost: { ...data, id: context.params.postId }
};
})
.catch(e => context.error());
},
methods: {
onSubmitted(editedPost) {
this.$store.dispatch("editPost", editedPost).then(() => {
this.$router.push("/admin");
});
}
}
};
</script>
The method from store is:
editPost(vuexContext, editedPost) {
return this.$axios
.$put(
"https://XXXX.com/posts.json" +
editedPost.id +
".json?auth=" +
vuexContext.state.token,
editedPost
)
.then(res => {
vuexContext.commit("editPost", editedPost);
})
.catch(e => console.log(e));
}
And my rules are:
{
"rules": {
".read": true,
".write": true
}
}
If you can help me with info regarding why I am not allowed, would owe you a lot!
Thank you!
Your URL contains two .json extensions, which won't work. You should only add .json after the full path of the JSON you are trying to write/update:
this.$axios
.$put(
"https://XXXX.com/posts/" +
editedPost.id +
".json?auth=" +
vuexContext.state.token,
editedPost
)

Properly rendering a task list using onSnapshot after adding/deleting items from the list

What I am making
I am making a simple task organization app using vue and firestore.
I made 5 functionalities so far.
Login
SignUp
Get and render a task list
Add / delete a task
[Not working!] Rendering any changes in list of tasks in realtime
Not working properly
It gets and loads array data from firestore and renders in realtime but, doesn't render properly
Issue detail
this issue becomes visible when it updates the list due to adding or deleting a task from the list.
Please check the image to get the clearer image of the issue.
Screenshots of issue
What I tried
Solve by refreshing the page but losing the point of having a realtime update.
Saw somewhere that set Vue () / new Vue () would solve, but did not. (Or more like I am too beginner to understand this concept to apply it...)
Most possibly I am not comprehending what's the real issue behind... So it would be great if anyone could point me out what's the real issue. So look forward to hear your ideas!
Code
There are mainly two files responsible for rendering list of tasks.
projectList.vue : where I get and load array datas and render the list of tasks
projectCard.vue : where I insert data of each tasks for projectList.vue to create the list.
(I will also add script for adding project; addProject.js just in case.)
projectList.vue : Get, load, render list of tasks
<template>
<div class="projectList">
<button class="home-buttons" #click="newProject">Add project</button>
<div v-if="createNew">
<projectAdd/>
</div>
<div v-show="loading">
<Loader/>
</div>
<div v-show="!loading">
<!--03 Pass array data to projectCard.vue then render the list of entries-->
<projectCard v-for="project in projects" :key="project.id" :project="project"/>
</div>
<p v-show="noproject">There is no project</p>
</div>
</template>
<script>
import firebase from '#/firebase/firestore';
import Loader from '#/components/loading.vue';
import projectCard from '#/components/projectCard.vue';
import projectAdd from '#/components/addProject.vue';
export default {
components: {
projectCard,
Loader,
projectAdd,
},
data() {
return {
userid: this.$route.params.userId,
//02 Put array data here
projects: [],
loading: true,
createNew: false,
};
},
created() {
//01 Get datas in realtime then pass an array data to projects: []
const db = firebase.firestore()
.collection('user')
.doc(this.userid) //$route.params.userId
.collection('projects')
.orderBy('createdAt', 'desc');
db
.onSnapshot((querySnapshot) => {
querySnapshot.forEach((doc) => {
this.projects.push(doc.data());
});
if (this.projects.length >= 0) {
this.loading = false;
} else if (this.projects.length <= 0) {
this.loading = false;
}
});
},
methods: {
newProject() {
if (this.createNew !== true) {
this.createNew = true;
} else {
this.createNew = false;
}
},
},
};
</script>
projectCard.vue : Insert each data in array
<template>
<div class="projectCard">
<div class="user-list">
<div class="columns">
<div class="column is-8">
<h3>{{ project.projectname }}</h3>
<p>{{ project.slug }}</p>
<p>Why : {{ project.why }}</p>
<p>{{ project.phase }}</p>
</div>
<div class="column is-4 right">
<router-link class="button is-primary" :to="{ name: 'viewproject', params: { projectId: project.slug }}">
Find out more!
</router-link>
<button #click="deleteProject"> Delete </button>
</div>
</div>
</div>
</div>
</template>
<script>
import firebase from '#/firebase/firestore';
export default {
name: 'ProjectCard',
props: {
// Holds array data from parent-component; projectList.vue
project: Object,
},
methods: {
// Delete a task
deleteProject() {
firebase.firestore().collection('user').doc(this.project.userId)
.collection('projects')
.where('slug', '==', this.project.slug)
.get()
.then((snapshot) => {
snapshot.forEach((doc => {
console.log(doc.data().slug);
doc.ref.delete();
alert('You have deleted the project!' + doc.data().slug);
}))
})
},
},
};
</script>
addProject.js : Add Task (this functionality is accessible from another component rendered in projectList.vue)
import firebase from '#/firebase/firestore';
export default {
addProject(createdAt, userId,projectname,why,phase){
const db = firebase.firestore().collection("user")
.doc(userId).collection("projects"); // "Project"という名前のコレクションへの参照を作成
db.add({
createdAt: createdAt,
userId: userId,
projectname: projectname,
why: why,
phase: phase,
slug: this.generateUUID(),
})
.then(function (docRef) {
console.log('Document written with ID: ', docRef.id);
alert('Well done! You have created a new project!');
})
.catch(function (error) {
console.error('Error adding document: ', error);
});
},
generateUUID() {
let d = new Date().getTime();
let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
},
};
Thank you for spending your valuable time to read this far and to help me out of this issue!
Looking forward to hear some ideas from you guys!
This is because each time the listener is triggered you receive the entire result of your query, i.e. all the docs corresponding to it.
You basically have two options:
Option 1: Re-initialize your array
Re-initialize your array before populating it, as follows:
created() {
const db = firebase.firestore()
.collection('user')
.doc(this.userid) //$route.params.userId
.collection('projects')
.orderBy('createdAt', 'desc');
this.projects = []; <-- See here
db
.onSnapshot((querySnapshot) => {
querySnapshot.forEach((doc) => {
this.projects.push(doc.data());
});
if (this.projects.length >= 0) {
this.loading = false;
} else if (this.projects.length <= 0) {
this.loading = false;
}
});
},
Option 2: Listen to actual changes
As explained in the doc, you can detect "the actual changes to query results between query snapshots".
For example, you could only handle the additions, as follows:
db
.onSnapshot((querySnapshot) => {
querySnapshot.docChanges().forEach((change) => {
if (change.type === "added") {
this.projects.push(change.doc.data());
}
//....
});
//....
});

How to add API script (from Dribble) into my Gatsby Site

I am trying to call my Dribble posts onto my Gatsby website.
I followed the tutorial by this article https://medium.com/#nithin_94885/dribbble-shots-in-your-website-v2-api-5945a355d106, where I generated my Access Token from Dribble (a unique code to allow my gatsby site to access my dribble posts).
I am having trouble figuring out where to add the script that calls the API in my gatsby site.
I have tried pasting it to my gatsby-node.js file (In the past I thought this was where the script should go)
I am quite the newbie.. if the script that calls the Dribble API looks like this:
// Set the Access Token
var accessToken = '9f061d26c5a8be96b17a81718959a67dd54ca9669ca41752777193f7cc5be7c3';
// Call Dribble v2 API
$.ajax({
url: 'https://api.dribbble.com/v2/user/shots?access_token='+accessToken,
dataType: 'json',
type: 'GET',
success: function(data) {
if (data.length > 0) {
$.each(data.reverse(), function(i, val) {
$('#shots').prepend(
'<a class="shot" target="_blank" href="'+ val.html_url +'" title="' + val.title + '"><div class="title">' + val.title + '</div><img src="'+ val.images.hidpi +'"/></a>'
)
})
}
else {
$('#shots').append('<p>No shots yet!</p>');
}
}
});
and my gatsby-node.js file looks like this:
const path = require('path');
const { createFilePath } = require('gatsby-source-filesystem');
// Look at every node when it is created
exports.onCreateNode = ({node, getNode, actions}) => {
// Check for markdown nodes
const { createNodeField } = actions;
if(node.internal.type === 'MarkdownRemark') {
// Create a slug out of the markdown filepath name
const slug = createFilePath({
node,
getNode,
basePath: 'projects'
});
// Add the newly created slug to the node itself
createNodeField({
node,
name: 'slug',
value: `/project${slug}`
});
}
};
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
return new Promise((resolve, reject) => {
graphql(`
{
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`).then(result => {
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.fields.slug,
component: path.resolve(`./src/templates/project.js`),
context: {
// Data passed to context is available in page queries as GraphQL variables.
slug: node.fields.slug,
},
})
})
resolve()
})
})
};
How can I add the script so that the API script will call my shots in Dribble to link back to it?
I expected this to be an easy solution but I have been struggling with this Dribble/Gatsby integration for days now. :(

Method not working from created hook Vue.js

I am trying to create a web app based on a database. Setup: NodeJS and a Vuejs 2 app generated with the CLI (with Webpack). Currently, I am using axios to retrieve records into an object. Based on that object I want to draw some svg lines from certain points to other points. The method works completely as designed when running it from an #click (v-on directive). However, when I try to add it to the created hook it doesn't work. No errors displayed. It's just not running. Does anyone no why? Code example below.
<template>
<div class="holder">
<step v-for="item in steps"></step>
<events v-for="point in points"></events>
<button #click= "createArrows">Test</button>
</div>
</template>
<script>
import axios from 'axios'
import Step from './Step.vue'
import Events from './Events.vue'
export default {
name: 'Graph',
data () {
return {
steps: '',
events: '',
points: []
},
components: {
Step, Events
},
methods: {
getSteps: function() {
let getsteps = this
axios.get('localhost:8000/api/steps')
.then(function (response) {
getsteps.steps = response.data
})
.catch(function (error) {
getsteps.steps = "Invalid request"
})
},
getEvents: function() {
let getevents = this
axios.get('localhost:8000/api/events')
.then(function (response) {
getevents.events = response.data
})
.catch(function (error) {
getevents.events = "Invalid request"
})
},
createArrows: function() {
},
created() {
this.getSteps(),
this.getEvents(),
this.createArrows()
}
}
EDIT: Promises are already included in the axios library. Since I am new to this concept I missed this one. Refactored code below:
methods: {
getData: function() {
let getdata = this
axios.all([
axios.get('localhost:8000/api/steps'),
axios.get('localhost:8000/api/events')
])
.then(axios.spread(function (stepResponse, eventResponse) {
console.log('success')
getdata.steps = stepResponse.data
getdata.events = eventResponse.data
getdata.createArrows()
}))
.catch(function (error) {
console.log("Invalid request")
})
},
createArrows: function() {
}
},
created() {
this.getData()
}
}
</script>
I think it's a classic async issue.
With v-on, your call to createArrows is "timewise after" getSteps and getEvents: meaning that getSteps and getEvents have finished executing their internal ajax promises, have populated the relevant data into the component instance for createArrows to find and access.
However, inside the created() hook, if you think about it, the calls fall through to createArrows() instantaneously (before the promisy things inside getSteps and getEvents have finished).
You'll have to refactor the call to createArrows inside created() as promise resolve for it work there correctly.

Categories