I have a vue3 web app. My issue is that once I try to navigate to a page using <router-link to ="/Dashboard"/>
Below is the Dashboard.vue
<template>
<div class="enquiry">
<div class="row">
<div class="col-6" v-for="(p, index) in keyAreas" :key="index">
<div class="card" style="margin-bottom: 10px">
<div class="card-body">
<h2 class="card-title">
{{ p.number }}
<span class="card-title" style="float: right">{{ p.title }}</span>
</h2>
<h5 class="card-text">
Properties for rent
<span class="card-title" style="float: right; margin-top: -5px">
<Doughnut
:chart-data="updateChartData(p.number, totalPropertiesNumber)"
:width="80"
:height="80"
/>
</span>
</h5>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { ref } from "vue";
import { projectDatabase } from "../../firebase/config";
import getUser from "../../composables/getUser";
import {
Chart as ChartJS,
Title,
Tooltip,
Legend,
ArcElement,
CategoryScale,
} from "chart.js";
ChartJS.register(Title, Tooltip, Legend, ArcElement, CategoryScale);
export default {
setup() {
//to get user info e.g email and display name
const { user } = getUser();
const company = ref("");
const keyAreas = ref([]);
//all LGAs
const allLGAs = ref([
{ title: "Abuja", number: 0 },
{ title: "Banana Island", number: 0 },
{ title: "Bluewaters Lagos", number: 0 },
{ title: "Benin City", number: 0 },
{ title: "Eko Atlantic", number: 0 },
]);
//Query Function for Specific Locations
const filterLocation = (item, query, filter) => {
if (item[filter] === query) {
return true;
}
return false;
};
//reference from firebase for user company
projectDatabase
.ref("users")
.child(user.value.uid)
.child("company")
.on("value", (snapshot) => {
company.value = snapshot.val();
//loop through all LGAs array and update dashboard by filtering each LGA for its properties in its field
allLGAs.value.forEach(function (p) {
p.number = Object.keys(snapshot.val())
.map((key) => {
snapshot.val()[key].id = key;
return snapshot.val()[key];
})
.filter((item) => {
return filterLocation(item, p.title, "location");
}).length;
if (p.number > 0) {
keyAreas.value.push(p);
}
});
});
return {
allLGAs,
company,
keyAreas,
};
},
};
</script>
The problem is every time i move to a new page, the page freezes and I have to refresh to see all the items in the v-for loop. This happens to about 3 pages on the web app. Is there a way to solve this?
I have also tried disabling all my browser extensions and things of that nature yet the problem still persists. Could it be because of the size of the array being loaded in the v-for?
OP solved his issue by finding out that Bootstrap v5 adds a class called offcanvas with
overflow: hidden;
overflow-x: hidden;
overflow-y: hidden;
Enabling the scrolling makes it functional again.
Related
I have shown vechicle data just I want to get driver data related to vehicle but unfortuntly i am getting error undefined please help me how can i show into draggablelist thank u ?
Controller
public function index(){
return $vehicles = Vehicle::with('driver')->get();
}
template view
<div class="row">
<div class="col-6">
<q-card-section>
<div class="tw-grid">
<div class="tw-col-span-6">
<DraggableList
v-model="api.drivers"
label-key="username"
:colors="colors"
/>
</div>
</div>
</q-card-section>
</div>
</div>
vue js
export default {
data () {
return {
api: {
vehicles: [],
drivers: []
}
}
},
mounted () {
this.fetchVehiclesDriver()
},
methods: {
fetchVehiclesDriver () {
this.$api.get(this.apiRoute('client.vector.driver', {
}))
.then(({ data }) => {
this.api.vehicles = data.vehicles
this.api.drivers = data.vehicles.driver
console.log(data.vehicles.driver) // undefined
})
}
}
}
I'm using WPGraphQL to query all of my posts from WordPress. And I'm using Astro to display a list of cards for each of those posts on the front-end.
Here is what that my GraphQL query looks like:
/* BASIC FETCH API */
async function fetchAPI(query, { variables } = {}) {
const headers = { "Content-Type": "application/json" };
const res = await fetch(API_URL, {
method: "POST",
headers,
body: JSON.stringify({ query, variables }),
});
const json = await res.json();
if (json.errors) {
console.log(json.errors);
throw new Error("Failed to fetch API");
}
return json.data;
}
/* ALL POSTS QUERY */
export async function getAllPosts() {
const data = await fetchAPI(`
{
posts(first: 10000) {
edges {
node {
id
title
content
excerpt
slug
categories(first: 2) {
nodes {
slug
name
}
}
featuredImage {
node {
sourceUrl
}
}
}
}
}
}
`);
return data?.posts;
}
And here is how I am rendering those posts on my blog page:
<Section>
<Container>
<div class="post--card--wrapper">
{page.data.map((post) => (
<PostCard
src={post.node.featuredImage.node.sourceUrl}
href={`/posts/${post.node.slug}`}
title={post.node.title}
excerpt={`${post.node.excerpt.slice(0, 120)}...`}
/>
))}
</div>
<div class="pagination--wrapper py-6">
{page.url.prev ? (
<a href={page.url.prev || "#"} class="pagination--previous">
← Previous
</a>
) : null}
{page.url.next ? (
<a href={page.url.next || "#"} class="pagination--next">
Next →
</a>
) : null}
</div>
</Container>
</Section>
And this is the code for the PostCard.astro component:
---
export interface Props {
href?: string;
src?: string;
alt?: string;
title?: string;
categories?: string;
excerpt?: string;
}
const { href, src, alt, title, categories, excerpt } = Astro.props;
---
<a href={href} class="post--card">
{src && <img src={src} alt={alt} class="post--thumbnail" />}
<div class="post--card--bottom">
<h5 class="post--card--heading">{title}</h5>
<div class="post--card--excerpt" set:html={excerpt}></div>
</div>
</a>
The problem is that a few of the posts do not have featured images set. And so, my builds are failing with the following error message:
"TypeError: Cannot read properties of null (reading 'node')"
I basically want to tell GraphQL to grab the featuredImage field for each post if it exists. But if featuredImage does not exist, keep going and get the rest of them.
Conditionally render elements in Astro
The answer to this in Astro is to conditionally render an element. This is a known pattern
all you have to do is add post.node.featuredImage && in front of the element to render conditionally
<div class="post--card--wrapper">
{page.data.map((post) => (
{post.node.featuredImage &&
<PostCard
...
/>
}
))}
</div>
{featuredImage &&
}
reference in Astro docs : https://docs.astro.build/en/tutorial/2-pages/3/#conditionally-render-elements
I am making an app that communicate with an api and fetch data,home page changes every day so i can't just add static components to it,
i need to create it according to the data that comes from the api.
i have a component for the home page called Home.vue
this component can have one or more Carousels depending on the data that i'am fetching.
i also have Carousel.vue which is responsible about displaying images and it had it's own props.
the question is :
How to add component to the dom from loop
this is Home.vue where i am making the loop :
<template>
<div>
<!--I Need The Loop right here-->
</div>
</template>
<script>
export default {
components: {},
data() {
return {
page_content: [],
widgets: [],
}
},
created() {
this.getHomeContent();
},
methods:
{
getHomeContent() {
window.axios.get(window.main_urls["home-content"]).then(response => {
this.page_content = JSON.parse(JSON.stringify(response.data));
console.log(this.page_content);
for (let index in this.page_content) {
switch (this.page_content[index].type) {
// if type is banner
case 'banner':
switch (this.page_content[index].display) {
// if display is carousel
case 'carousel':
console.log('carousel')
// end if display is carousel
this.widgets.push({
'type': 'Carousel',
'images': this.page_content[index].items,
})
}
// end if type is banner
}
}
});
}
}
}
</script>
and this is Carousel.vue which i need to be imported when needed with passing props :
<template>
<div>
<div >
<VueSlickCarousel>
<div v-for="image in images">
<img src="{{img}}">
</div>
</VueSlickCarousel>
</div>
</div>
</template>
<script>
import VueSlickCarousel from 'vue-slick-carousel'
import 'vue-slick-carousel/dist/vue-slick-carousel.css'
import 'vue-slick-carousel/dist/vue-slick-carousel-theme.css'
export default
{
components: {VueSlickCarousel},
name:'Carousel',
props:[
'images'
],
methods:
{
}
}
</script>
how to add Carousel.vue component to Home.vue dynamically some thing like:
if(data.display == 'carousel')
{
<carousel images="data.images"></carousel>
}
Import the component to your Home.vue :
import Carousel from './Carousel.vue'
export default {
components: {Carousel},
}
Then loop in your template:
<carousel v-for="(widget,index) in widgets" :key="index" :images="widget.images"/>
Best to use a widget.id rather than index for the key prop
This is the correct answer !
<template>
<div>
<template v-for="widget in widgets">
<div v-if="widget.type == 'carousel'" :key="widget.type">
<carousel
:images="widget.images"
:arrows ="widget.arrows"
:dots = "widget.dots"
>
</carousel>
</div>
</template>
</div>
</template>
<script>
import Carousel from './widgets/Carousel.vue'
export default {
components: {Carousel},
data() {
return {
page_content: [],
widgets: [],
}
},
created() {
this.getHomeContent();
},
methods:
{
getHomeContent() {
window.axios.get(window.main_urls["home-content"]).then(response => {
this.page_content = JSON.parse(JSON.stringify(response.data));
console.log(this.page_content);
for (let index in this.page_content) {
switch (this.page_content[index].type) {
// if type is banner
case 'banner':
switch (this.page_content[index].display) {
// if display is carousel
case 'carousel':
console.log('carousel')
// end if display is carousel
this.widgets.push({
'type': 'carousel',
'arrows':true,
'dots':true,
'images': this.page_content[index].items,
})
}
// end if type is banner
}
}
});
}
}
}
</script>
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'an not using getters.js file seperately, instead getters are written in js->assets->store->modules->user.js file
This is my user.js
const state = {
count : '',
list:[]
};
const mutations = {
COUNT: (state, data) => {
state.count = data
},
LIST : (state, data) => {
state.list = data
}
};
const getters = {
userCount:(state) => state.list.length
};
const actions = {
getList: ({commit,state}) => {
axios.get('/api/user/list')
.then((response) => {
commit('LIST', response.data);
})
}
};
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
This is my user vue component-user.vue
<template>
<div class="col-lg-3 col-xs-6">
<div class="small-box bg-yellow">
<div class="inner">
<h3>{{ usercount }}</h3>
<p>User Registrations</p>
</div>
<div class="icon">
<i class="ion ion-person-add"></i>
</div>
View <i class="fa fa-arrow-circle-right"></i>
</div>
</div>
</template>
<script>
export default{
computed: {
usercount() {
return this.$store.getters['user/userCount'];
}
},
mounted(){
this.$store.dispatch('user/getList');
}
}
</script>
In user.js,
alert(state.list.length)
gives the correct count in the alert box.
But in user.vue,
alert(this.$store.getters['user/userCount'])
gives 'undefined'
remove unnecessary : from this:
const getters = {
userCount (state) => state.list.length
};
In the Api controller, I'am using paginate() instead of get().vue dev tools helped me to find out this...
getList: ({commit,state}) => {
axios.get('/api/user/list')
.then((response) => {
commit('LIST', response.data);
})
}
changed response.data to response.data.data