I am not sure what I am doing wrong here, still pretty noob at vue js so that might be the problem.
The problem is that it does not display anything. I got it to work with older vue version with a bit different code, but yeah...
var App = Vue.extend({});
var postList = Vue.extend({
template:'#post-list-template',
data: function(){
return {
posts: ''
}
},
mounted: function(){
posts = this.$http.get('/wp-json/wp/v2/posts?per_page=10');
posts.get(function(posts){
this.$set('posts', posts);
})
}
});
var router = new VueRouter({
mode: 'history',
routes: [
{ path: '/', component: postList}
]
});
new Vue({
el: '#app',
router: router,
template: '<router-view></router-view>'
});
HTML is here if that makes things a bit easier to understand :
<div class="container-fluid projects" id="projects">
<h1 class="text-center project-heading">Projects</h1>
<div class="white-wrap">
<div id="app">
<router-view></router-view>
</div>
</div>
<template id="post-list-template">
<div class="container">
<div class="post-list">
<article v-for="post in posts">
<div class="post-content">
<h2>{{ post.title.rendered }}</h2>
{{ post.id }}
</div>
</article>
</div>
</div>
</template>
</div>
This resolved my problem:
var postLists = Vue.component('post-list',{
template:'#post-list-template',
data: function () {
return {
posts:'',
}
},
mounted:function () {
this.$http.get('./wp-json/wp/v2/posts').then(response => {
// get body data
this.posts = response.body;
this.posts.forEach(function (){
} );
}, response => {
console.log('Not Found');
});
}
});
//router
var router = new VueRouter({
routes: [
{ path: '', component: postLists },
]
});
new Vue({
el: '#app',
router: router,
});
Related
there are two components Dashboard and Apps and they have children. What I want to do is, when clicking any of the Main Components
showMenu is showing but,
I don't want the main components to be opened. and I want the main components and active class to be written
I want it to act as Dashboard and Appsself
app.vue
<template>
<router-link :to="{name:'dashboard'}" #click="isShow('dashboard')">Dashboard</router-link>
<router-link :to="{name:'apps'}" #click="isShow('apps')">Apps</router-link>
<div class="children">
<div class="dashboard" v-show="showName ==='dashboard' && showMenu">
<router-link exact :to="{name:'home'}">Home</router-link>
<router-link exact :to="{name:'about'}">About</router-link>
</div>
<div class="apps" v-show="showName ==='apps' && showMenu">
<router-link exact :to="{name:'setting'}">Setting</router-link>
<router-link exact :to="{name:'profile'}">Profile</router-link>
</div>
</div>
<div class="container">
<router-view/>
</div>
</template>
<script setup>
const showName = ref('')
const showMenu = ref(false)
function isShow(name) {
if (showName.value !== name) {
showMenu.value = true
}
if (showName.value === name) {
showMenu.value = !showMenu.value
} else {
showName.value = name
}
}
</script>
router.js
import {createRouter, createWebHistory, RouterView} from 'vue-router'
const routes = [
{
path: '/dashboards',
name: 'dashboards',
component: RouterView,
children: [
{
path: 'home',
component: () => import('../Views/home.vue'),
name: 'home',
},
{
path: 'about',
component: () => import('../Views/about.vue'),
name: 'about',
},
]
},
{
path: '/apps',
name: 'apps',
component: RouterView,
children: [
{
path: 'setting',
component: () => import('../Views/setting.vue'),
name: 'setting',
},
{
path: 'profile',
component: () => import('../Views/profile.vue'),
name: 'profile',
},
]
},
];
const router = createRouter({
linkActiveClass: "item-active",
linkExactActiveClass: "exact-active",
history: createWebHistory(),
routes
})
export default router;
I'm creating a blog with free sewing patterns as content. I'm using route parameters to receive each blog individually. However, I'm getting a blank page when trying to retrieve its data from firebase firestore. Please help.
The blog's id appears on my address bar:
http://localhost:8080/#/admin/single-pattern/4LIS362IEWa7RKEv79g8
But it renders a blank page. I cant see my blog content.
This is my route path code. I've added a parameter of :id in my singlepattern. The SinglePattern component is where I will get the individual blog's data:
{
path: "/admin",
name: "admin",
component: Admin,
meta: {
auth: true,
},
children: [
{
path: "dashboard",
name: "dashboard",
component: Dashboard,
},
{
path: "manage-patterns",
name: "manage-patterns",
component: ManagePatterns,
},
{
path: "single-pattern/:id",
name: "single-pattern",
component: SinglePattern,
},
],
},
Here is my "ListPattern" component's code. ListPattern is where all my sewing blogs are displayed.
<template>
<div class="list-blogs">
<h1>LIST BLOG TITLES</h1>
<br />
<input type="text" v-model="search" placeholder="search blogs" />
<div
class="blog-cover"
v-for="pattern in filteredPatterns"
:key="pattern.id"
>
<div>
<router-link v-bind:to="'/admin/single-pattern/' + pattern.id">
<h3 style="cursor: pointer" v-rainbow>
{{ pattern.title | uppercase }}
</h3></router-link
>
</div>
<p
:style="'background-color: var(--lightgrey)'"
:inner-html.prop="pattern.description | snippet"
></p>
</div>
</div>
</template>
<script>
import firebase from "firebase";
import searchMixin from "../mixins/searchMixin";
// Basic Use - Covers most scenarios
import { VueEditor } from "vue2-editor";
import Quill from "quill";
const AlignStyle = Quill.import("attributors/style/align");
Quill.register(AlignStyle, true);
// import $ from "jquery";
import Swal from "sweetalert2";
window.Swal = Swal;
const Toast = Swal.mixin({
toast: true,
position: "top-end",
showConfirmButton: false,
timer: 3000,
});
window.Toast = Toast;
export default {
name: "ManagePatterns",
components: { VueEditor },
data() {
return {
patterns: [],
pattern: {
title: null,
description: null,
image: null,
},
search: "",
};
},
firestore() {
return {
patterns: firebase.firestore().collection("free-patterns"),
};
},
computed: {},
},
};
</script>
And this is my 'SinglePattern' component where the clicked blog/pattern is displayed.
<template>
<div class="single-pattern">
<div class="blog-cover">
<div>
</div>
<div v-if="pattern">
<h3 style="cursor: pointer">
{{ pattern.title }}
</h3>
<div v-if="pattern.description">
<p
:style="'background-color: var(--lightgrey)'"
:inner-html.prop="pattern.description"
></p>
</div>
</div>
</div>
</div>
</template>
<script>
import firebase from "firebase";
import searchMixin from "../../mixins/searchMixin";
export default {
data() {
return {
id: this.$route.params.id,
patterns: [],
pattern: {
title: null,
description: null,
image: null,
},
};
},
firestore() {
return {
patterns: firebase.firestore().collection("free-patterns"),
};
},
mixins: [searchMixin],
created() {
console.log(this.$route.params.id);
var pat = this;
firebase
.firestore()
.collection("free-patterns")
.doc(this.$route.params.id)
.get()
.then(function(doc) {
if (doc.exists) {
pat.pattern = doc.data().pattern;
} else {
console.log("no such doc");
}
});
},
methods: {},
};
</script>
It works. I just had to change the code in my created() hook in 'SingePattern' component.
created() {
console.log(this.$route.params.id);
var docRef = firebase
.firestore()
.collection("free-patterns")
.doc(this.$route.params.id);
docRef
.get()
.then((doc) => {
if (doc.exists) {
this.pattern = doc.data();
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
})
.catch((error) => {
console.log("Error getting document:", error);
});
I got the user profile from the Realtime database but when I have more than 1 account I get the second user profile too.
Here below you see the data from 2 users. But I want to get the user that is loggend in and that is the currentUser
The ID is the currentUser
This is the Realtime database:
This is my Profile.vue page:
<div class="container" v-for="profileData of profile" :key="profileData['.key']">
<div v-if="seen" class="row">
<div class="col">
<div class="card card-border" style="width: 30rem;">
<div class="card-body">
<h4 class="card-title text-center mb-4">Personal information</h4>
<p class="card-text">ID: {{profileData.CurrentUser}}</p>
<p class="card-text">First name: {{profileData.firstName}}</p>
<p class="card-text">Last name: {{profileData.lastName}}</p>
<p class="card-text">Phone number: {{profileData.phoneNumber}}</p>
<p class="card-text">Adress: {{profileData.adress}}</p>
<p class="card-text">Citizenship: {{profileData.citizenship}}</p>
<p class="card-text">Personal email: {{profileData.personalEmail}}</p>
</div>
</div>
</div>
<div class="col"></div>
<div class="col">
<div class="card card-border" style="width: 30rem;">
<div class="card-body">
<h4 class="card-title text-center mb-3">Business information</h4>
<p>Company name: {{profileData.companyName}}</p>
<p>Chamber Of Commerce Number: {{profileData.chamberOfCommerceNumber}}</p>
<p>Street: {{profileData.street}}</p>
<p>House number: {{profileData.houseNumber}}</p>
<p>ZIP code: {{profileData.zipCode}}</p>
<p>Location: {{profileData.location}}</p>
<p>Company email: {{profileData.companyEmail}}</p>
</div>
</div>
</div>
</div>
</div>
I added a if/else in the created() section below.
And this is the script:
<script>
import firebase from "firebase";
import { db } from '../../config/db';
export default {
data() {
return {
email: "",
password: "",
profileData: [],
isHidden: true,
seen: true,
isLoggedIn: false
}
},
firebase: {
profile: db.ref('profile')
},
methods: {
resetPassword() {
const auth = firebase.auth();
auth.sendPasswordResetEmail(auth.currentUser.email).then(() => {
console.log('Email send');
// Email sent.
}).catch((error) => {
// An error happened.
console.log(error);
});
}
},
created() {
if(firebase.auth().currentUser) {
this.isLoggedIn = true;
this.currentUser = firebase.auth().currentUser.email;
}
var user = firebase.auth().currentUser;
if (this.user == this.profileData.CurrentUser) {
this.seen = true;
} else {
this.seen = false;
}
}
};
</script>
In this Profile.vue page I have the add function:
AddProfile() {
console.log(JSON.stringify(this.profileData) + this.currentUser)
this.$firebaseRefs.profile.push({
firstName: this.profileData.firstName,
lastName: this.profileData.lastName,
phoneNumber: this.profileData.phoneNumber,
adress: this.profileData.adress,
citizenship: this.profileData.citizenship,
personalEmail: this.profileData.personalEmail,
companyName: this.profileData.companyName,
chamberOfCommerceNumber: this.profileData.chamberOfCommerceNumber,
street: this.profileData.street,
houseNumber: this.profileData.houseNumber,
zipCode: this.profileData.zipCode,
location: this.profileData.location,
companyEmail: this.profileData.companyEmail,
CurrentUser: this.currentUser
})
this.profileData.firstName = '';
this.profileData.lastName = '';
this.profileData.phoneNumber = '';
this.profileData.adress = '';
this.profileData.personalEmail = '';
this.profileData.companyName = '';
this.profileData.chamberOfCommerceNumber = '';
this.profileData.street = '';
this.profileData.houseNumber = '';
this.profileData.zipCode = '';
this.profileData.location = '';
this.profileData.companyEmail = '';
this.CurrentUser = '';
window.scrollTo(0,0, 0,0);
console.log('Added to database');
/* Waiting for 2 seconds here */
this.$router.push('/internship')
},
Apparently you are using Vuefire.
As you will see in the Vuefire documentation, by doing
firebase: {
profile: db.ref('profile')
},
you are using a declarative biding on the profile Realtime Database node and therefore it is normal that you get all the children of this node.
If you just want to display the node corresponding to the current user, you could use the programmatic binding, along the following lines:
<template>
<div class="home">
{{user}}
<ol></ol>
</div>
</template>
<script>
import { db } from "../firebase";
const profile = db.ref("profile");
export default {
name: "demo",
data() {
return {
user: null,
id: null
};
},
watch: {
id: {
immediate: true,
handler(id) {
this.$rtdbBind("user", profile.child(id));
}
}
},
created() {
if (firebase.auth().currentUser) {
this.id = currentUser.uid;
}
}
};
</script>
I'm making a captcha component using vue. I try to fetch the captcha when the component created. When I do this in a async manner, the page will not be reactive, although the state has already been updated. But I when do it in sync manner, everything is fine. So, I'm wondering why async manner won't work?
This works
<template>
<section>
<div class="captcha-container">
<div v-if="captcha" v-html="captcha.data"></div>
</div>
</section>
</template>
<script>
import { mapState, mapActions } from "Vuex";
export default {
created: function() {
this.$store.commit('setCaptcha', {id: 'xx', data:'Hi'});
},
computed: {
...mapState(["captcha"])
},
};
</script>
This does not work
<template>
<section>
<div class="captcha-container">
<div v-if="captcha" v-html="captcha.data"></div>
</div>
</section>
</template>
<script>
import { mapState, mapActions } from "Vuex";
export default {
created: function() {
setTimeout(() => {
this.$store.commit('setCaptcha', {id: 'xx', data:'Hi'});
}, 1000);
},
computed: {
...mapState(["captcha"])
},
};
</script>
I tried to auth using vue.js and firebase.
and error occurs router.beforeEach function,
Anyone has any idea why it might happen?
console error
vue-router.esm.js?fe87:16 [vue-router] uncaught error during route navigation:
warn # vue-router.esm.js?fe87:16
abort # vue-router.esm.js?fe87:1904
iterator # vue-router.esm.js?fe87:1968
step # vue-router.esm.js?fe87:1717
runQueue # vue-router.esm.js?fe87:1725
confirmTransition # vue-router.esm.js?fe87:1972
transitionTo # vue-router.esm.js?fe87:1874
push # vue-router.esm.js?fe87:2181
(anonymous) # vue-router.esm.js?fe87:1960
(anonymous) # index.js?3672:44
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import addPost from '#/components/addPost'
import showPost from '#/components/showPost'
import Login from '#/components/Login'
import SignUp from '#/components/SignUp'
import firebase from 'firebase'
Vue.use(Router)
const router = new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'app',
component: showPost
},
{
path: '/add',
component: addPost,
meta: {
requiresAuth: true
}
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/signup',
name: 'SignUp',
component: SignUp
}
]
})
router.beforeEach((to, from, next) => {
let currentUser = firebase.auth().currentUser;
let requiresAuth = to.matched.some(record => record.meta.requiresAuth);
if (requiresAuth && !currentUser) next('/login')
else if (!requiresAuth && currentUser) next('/')
else next()
})
export default router
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import VueFire from 'vuefire'
import firebase from 'firebase'
Vue.use(VueFire)
Vue.config.productionTip = false
let app;
firebase.auth().onAuthStateChanged(function(user) {
if(!app) {
app = new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
}
})
App.vue
<template>
<div id="app">
<app-header></app-header>
<router-view></router-view>
<button #click="logout">Logout</button>
</div>
</template>
<script>
import header from './components/header'
import firebase from 'firebase'
export default {
name: 'app',
components: {
'app-header': header
},
methods: {
logout: function() {
firebase.auth().signOut().then(() => {
this.$router.replace('login')
})
}
}
}
</script>
Login.vue
import firebase from 'firebase'
import db from '../firebaseInit'
const postRef = db.ref('posts')
export default {
name: 'login',
data: function() {
return {
email: '',
password: ''
}
},
methods: {
signIn: function() {
firebase.auth().signInWithEmailAndPassword(this.email, this.password).then(
(user) => {
this.$router.replace('/')
},
(err) => {
alert('Oops ' + err.message)
}
);
}
}
}
</script>
addPost.vue
<template>
<div id="add-blog">
<h2>Add a New Post</h2>
<form v-if="!submitted">
<label>Title:</label>
<input type="text" v-model="newPost.title" required />
<p>{{ getDate }}</p>
<label for="">Content:</label>
<textarea v-model.trim="newPost.content"></textarea>
<div id="checkboxes">
<p>Categories:</p>
<label>Vue.js</label>
<input type="checkbox" value="vue" v-model="newPost.categories" />
<label>CSS Magic</label>
<input type="checkbox" value="css" v-model="newPost.categories" />
</div>
<label>Author:</label>
<select v-model="newPost.author">
<option v-for="author in authors">{{ author }}</option>
</select>
<button #click.prevent="addPost">Add Post</button>
</form>
<div v-if="submitted">
<p>Congraturation!</p>
</div>
<div id="preview">
<h3>Preview Post</h3>
<h4>Title {{ newPost.title }}</h4>
<h4>Content </h4>
<p style="white-space: pre">{{ newPost.content }}</p>
<ul>
<li v-for="category in newPost.categories">{{ category }}</li>
</ul>
<p>{{ newPost.author }}</p>
</div>
</div>
</template>
<script>
import db from '../firebaseInit'
const postRef = db.ref('posts')
export default {
data() {
return {
newPost: {
date: '',
title: '',
author: '',
content: '',
categories: []
},
authors: ['Naeun', 'Raphael'],
submitted: false,
items: []
}
},
methods: {
addPost: function() {
postRef.push(this.newPost)
this.newPost.date = '',
this.newPost.title = '',
this.newPost.author = '',
this.newPost.content = '',
this.newPost.categories = ''
},
removePost: function() {
postRef.child(post['.key']).remove()
}
},
computed: {
getDate: function() {
const toTwoDigits = num => num < 10 ? '0' + num : num;
let today = new Date();
let year = today.getFullYear();
let month = toTwoDigits(today.getMonth() + 1);
let day = toTwoDigits(today.getDate());
return this.newPost.date = `${year}-${month}-${day}`;
}
}
}
</script>
Make sure that the next function is called exactly once in any given pass through the navigation guard. It can appear more than once, but only if the logical paths have no overlap, otherwise the hook will never be resolved or produce errors.
Your else if condition else if (!requiresAuth && currentUser) next('/') violates this rule.
Change your route guarding logic
// check if route requiresAuth
router.beforeEach((to, from, next) => {
if (to.matched.some(rec => rec.meta.requiresAuth)) {
const user = firebase.auth().currentUser;
// check auth state of user
user ? next() : next('/login') // user not signed in, route to login
} else {
next(); // route does not require auth
}
});
https://router.vuejs.org/guide/advanced/navigation-guards.html#global-before-guards
Hope this helps.