Data not showing on Firebase, Using V-data-table Vue.js - firebase

The data is not showing, I do not know how to push the value from the firebase to the v-data-table values. Here is my code.
<template>
<div class="dashboard">
<h2 class="subheading mx-5">Subject</h2>
<v-btn block color="primary mt-5" #click="enrollSubjects()">Enroll Subjects</v-btn>
<v-container class="my-5">
<template>
<v-card>
<v-card-title>
Courses
<v-spacer></v-spacer>
<v-text-field v-model="search" append-icon="search" label="Search" single-line hide-details></v-text-field>
</v-card-title>
<v-data-table v-model="selected" :headers="headers" :items="courses" show-select :single-select="singleSelect" item-key="descrip_title" :search="search">
</v-data-table>
</v-card>
</template>
</v-container>
</div>
</template>
<script>
// # is an alias to /src
import db from '#/firebase/init'
export default {
name: 'dashboard',
data(){
return{
search: '',
singleSelect: false,
subjects: [],
selected: [],
headers: [
{text: 'Control No.', value: 'controlno'},
{text: 'Course No.', value: 'courseno'},
{text: 'Descriptive Title', value: 'descrip_title'},
{text: 'Schedule(In)', value: 'schedin'},
{text: 'Schedule(Out)', value: 'schedout'},
{text: 'Room No.', value: 'roomno'},
{text: 'Days', value: 'days'},
{text: 'Units', value: 'units'}
],
courses: []
}
},
methods:{
enrollSubjects(){
if(this.selected === this.selected){
this.$swal({
title: 'No Course Selected',
text: 'Please select course/s',
type: 'error'
})
}
},
created(){
db.collection('masterlist_courses').get()
.then(snapshot => {
snapshot.forEach(doc => {
let course = doc.data()
course.id = doc.id
this.courses.push(course)
})
})
}
}
}
</script>
I am practicing in firebase and vuetify, I do not know how to push this to the value of the v-data-table. I am having hard time and its not showing anything to the datatable and also there is no error. It's not saying anything after I code the data in the firebase not displaying

You need to use one of the vue.js life cycle hook to trigger the fetch before the component is mounted.
For example the created hook can be used to "run code after an instance is created", as follows:
<script>
// # is an alias to /src
import db from '#/firebase/init'
export default {
name: 'dashboard',
data(){
return{
search: '',
singleSelect: false,
subjects: [],
selected: [],
headers: [
{text: 'Control No.', value: 'controlno'},
{text: 'Course No.', value: 'courseno'},
{text: 'Descriptive Title', value: 'descrip_title'},
{text: 'Schedule(In)', value: 'schedin'},
{text: 'Schedule(Out)', value: 'schedout'},
{text: 'Room No.', value: 'roomno'},
{text: 'Days', value: 'days'},
{text: 'Units', value: 'units'}
],
courses: []
}
},
methods:{
enrollSubjects(){
if(this.selected === this.selected){
this.$swal({
title: 'No Course Selected',
text: 'Please select course/s',
type: 'error'
})
}
}
},
created: function() {
db.collection('masterlist_courses').get()
.then(snapshot => {
snapshot.forEach(doc => {
let course = doc.data()
course.id = doc.id
this.courses.push(course)
})
})
}
}
</script>
Note that if the query to Firestore is going to take some time, you could display a spinner and hide it when the query is done, i.e. in the callback passed to then(), after snapshot.forEach().

You need to define what items should be shown. You have only defined your headers so far. Try it like this for every header you have.
<template v-slot:item.controlno="{ item }">
{{ item.controlno }}
</template>
Hope this helps =)

Related

In Sanity/Nextjs, how do I make a page of categories that can open a new page with the selected categories subcategories?

I'm using nextjs for my frontend, and sanity for my backend. I have a page that shows a list of categories (e.g., sketches, paintings, exhibitions) and each have their own subcategories (e.g., exhibitions -> place a, place b, place c; sketches -> set a, set b, set c, set d). When you select one of those subcategories (e.g., place b), it will open a page with everything in that chosen subcategory.
I want to make it so that if the user clicks a category on one webpage, it will open a new webpage with its specific subcategories (children?).
Here are my schemas for the categories ('category') and subcategories ('set'):
// category.js
export default {
name: 'category',
type: 'document',
title: 'Category',
fields: [
{
name: 'category_name',
type: 'string',
title: 'Category Name'
},
{
name: 'category_image',
type: 'image',
title: 'Category Image'
},
{
name: 'categoryImage_alt',
title: 'Alt',
type: 'string'
},
{
name: 'contained_sets',
type: 'array',
title: 'Contained Sets',
of: [{
type: 'reference',
to: [{type: 'set'}]
}]
}
]
}
// setsSchema.js
export default {
name: 'set',
type: 'document',
title: 'Set',
fields: [
{
name: 'set_name',
type: 'string',
title: 'Set Name',
},
{
name: 'set_images',
type: 'array',
title: 'Set Images',
of: [
{
name: 'image',
type: 'image',
title: 'Image',
options: {
hotspot: true,
},
fields: [
{
name: 'alt',
type: 'string',
title: 'Alternative Text',
options: {
isHighlighted: true
}
},
{
name: 'name',
type: 'string',
title: 'Name',
options: {
isHighlighted: true
}
},
{
name: 'date',
type: 'string',
title: 'Date',
options: {
isHighlighted: true
}
},
{
name: 'size',
type: 'string',
title: 'Size',
options: {
isHighlighted: true
}
},
{
name: 'materials',
type: 'string',
title: 'Materials',
options: {
isHighlighted: true
}
},
]
},
]
},
{
name: 'slug',
title: 'Slug',
type: 'slug',
options: {
source: 'set_name'
}
}
]
}
This is my webpage with the categories:
import React, { useState, useEffect } from 'react';
import { client, urlFor } from '../lib/client';
import { Header, Footer } from '../components';
import Link from 'next/link';
const gallery = () => {
// fetches sanity data
const [categoryData, setCategories] = useState(null);
useEffect(() => {
client.fetch(
`*[_type=="category"]{
categoryImage_alt,
category_image{
asset->{
_id,
url
}
},
category_name,
contained_sets
}`)
.then((data) => setCategories(data))
.catch(err => console.error(err));
}, [] );
return (
<div>
<Header />
<main className="main-gallery">
<div className="title">
<div className="title-line-left"></div>
<h2>categories</h2>
<div className="title-line-right"></div>
</div>
<div className="categories">
<ul className="categories-container">
{categoryData && categoryData.map((category, index) => (
<li>
<Link href="/sets"><img src={urlFor(category.category_image).auto('format').url()} alt={category.categoryImage_alt}/></Link>
</li>
))}
</ul>
</div>
</main>
<Footer />
</div>
)
}
export default gallery
This page is for sets, which currently shows all of the sets/subcategories, and not just the selected categories subcategories. I've tried a couple things but nothing has worked.
import React, { useState, useEffect } from 'react';
import { client, urlFor } from '../lib/client';
import { Header, Footer } from '../components';
const sets = () => {
// fetches sanity data
const [galleryData, setGalleryData] = useState(null);
useEffect(() => {
client.fetch(
`*[_type=="set"]{
set_name,
slug,
set_images,
image{
asset->{
_id,
url
}
},
}`)
.then((data) => setGalleryData(data))
.catch(err => console.error(err));
}, [] );
return (
<div>
<Header />
<main className="main-gallery">
<div className="title">
<div className="title-line-left"></div>
<h2></h2>
<div className="title-line-right"></div>
</div>
<div className="categories">
<ul className="categories-container">
{galleryData && galleryData.map((set, index) => (
<li>
<img src={urlFor(set.set_images[0]).auto('format').url()} alt={set.set_name}/>
</li>
))}
</ul>
</div>
</main>
<Footer />
</div>
)
}
export default sets

React onClick not changing color of item

I am trying to make it so that when i click a note, the item should become selected and then it will change background color.
I have a console log statement inside the handleNoteClick function, but it is not logging, meaning that the function is not being called
import React, { useState } from "react";
import { NoteItems } from "../noteDisplay/noteDisplay";
import NavItems from "./navItems";
const NoteNav = () => {
const [notes, setNotes] = useState(NoteItems);
const handleNoteClick = (id) => {
const newNoteItems = notes.map((item) => {
if (item.id === id) return { ...item, selected: !item.selected };
else {
return item;
}
});
console.log("yekaj;lksndf");
setNotes(newNoteItems);
};
return (
<nav className="nav-bar">
<div className="nav-content">
{NoteItems.map((items) => (
<NavItems key={items.id} items={items} onClick={handleNoteClick} />
))}
</div>
</nav>
);
};
export default NoteNav;
Array of notes:
const NoteItems = [
{
id: uuidv4(),
message: "asdfasdfffffffffffffffffffffffffffffffffffffff",
title: "New Note",
selected: false
},
{
id: uuidv4(),
message: "asdfffffffffffffffffffffffffffffffffffffff",
title: "e"
},
{
id: uuidv4(),
message: "asdfasdfffffffffffffffffffffffffffffffffffffff",
title: "New Note",
selected: false
},
{
id: uuidv4(),
message: "asdfasdfffffffffffffffffffffffffffffffffffffff",
title: "New Note",
selected: false
},
{
id: uuidv4(),
message: "asdfasdfffffffffffffffffffffffffffffffffffffff",
title: "New Note",
selected: false
},
{
id: uuidv4(),
message: "asdfasdfffffffffffffffffffffffffffffffffffffff",
title: "New Note",
selected: false
},
{
id: uuidv4(),
message: "asdfasdfffffffffffffffffffffffffffffffffffffff",
title: "New Note",
selected: false
},
{
id: uuidv4(),
message: "asdfasdfffffffffffffffffffffffffffffffffffffff",
title: "New Note",
selected: false
},
{
id: uuidv4(),
message: "asdfasdfffffffffffffffffffffffffffffffffffffff",
title: "New Note",
selected: true
}
];
The object that I pass each item of the array into
import React, { useState } from "react";
const NavItems = ({ items }) => {
return (
<div
className={
items.selected ? "second-note-box-selected" : "second-note-box"
}
>
<h1 className="note-title">{items.title}</h1>
<p className="note-content">{items.message}</p>
</div>
);
};
export default NavItems;
There are a couple of problems with your code.
The first and most important is that onClick only works on native DOM elements. What you are doing here <NavItems key={items.id} items={items} onClick={handleNoteClick}/> is passing a prop named onClick to NavItems.
That will not trigger an on click, you need to use that in the component and attach it to a div for instance.
The second is regarding the fact that you are updating notes, but you don't use it during the render.
The third could be that you are iterating over the entire array, just to update one value. You could easily do something like this:
const handleNoteClick =(item) => {
item.selected = !item.selected
console.log('yekaj;lksndf')
setNotes([...notes])
}
And pass item as the argument to handleNoteClick like this:
<NavItems onClick={() => handleNoteClick(item) />
in this line that you mapped your items into NavItem
{NoteItems.map((items)=><NavItems key={items.id} items={items} onClick={handleNoteClick}/>)}
the onClick just point to the function and you cant pass pointer like handleNoteClick(id) because its excuted not pointed and your not passing the id to the function though
do this i think it should work
{NoteItems.map((items)=><NavItems key={items.id} items={items} onClick={()=>handleNoteClick(items.id)}/>)}
and of course you should pass custom prop onClick to your custom component native onclick

Vue.js - Invalid prop: type check failed for prop "src". Expected String, Object, got Promise

I'm trying to get an image inserted into my firebase's firestore and storage and display it on a v-card
my v-card code:
<v-row>
<v-col cols="3" v-for="massage in massages" :key="massage.id">
<v-card
class="mx-auto"
max-width="400"
>
<v-img
v-if="massage.image"
class="white--text align-end"
height="200px"
:src="massage.image"
>
</v-img>
<v-card-title>{{massage.title}}</v-card-title>
<v-card-text class="text--primary">
<div>{{massage.shortDescription}}</div>
</v-card-text>
<v-card-actions>
<v-btn
color="orange"
text
#click="goTodetail(massage.id)"
>
Explore
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
my script:
<script>
import{ db, storage} from '#/firebase.js';
export default {
el: '#vue',
name: 'BaseHeading',
// massId:this.$route.params.Pid,
components: {
BaseInfoCard: () => import('#/components/base/InfoCard'),
},
data() {
return{
massages:[],
showmassage: false,
showrehabilitation: false,
showsupport: false,
modal_1: true,
modal_2: false,
modal_3: false,
}
},
created() {
try{
db.collection("massages").get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
let img = ''
if(doc.data().image){
img = storage.ref().child(doc.data().image).getDownloadURL()
}
this.massages.push({
id: doc.id,
title: doc.data().title,
shortDescription: doc.data().shortDescription,
image: img
})
})
});
}catch(e){
console.log(e)
}
},
}
</script>
I think it provides promise but cannot figure out how to deal with it. The error is Invalid prop: type check failed for prop "src". Expected String, Object, got Promise.
I tried to put the following in the props:
props: {
src: [ String, Object],
},
but I still have the same error
Resolve the Promise when retrieving the image URL, before you pass it into your massage object.
created() {
try {
db.collection('massages')
.get()
.then((querySnapshot) => {
querySnapshot.forEach(async (doc) => {
// start pertinent change
if (doc.data().image) {
storage
.ref()
.child(doc.data().image)
.getDownloadURL()
.then((url) => {
this.massages.push({
id: doc.id,
title: doc.data().title,
shortDescription: doc.data().shortDescription,
image: url,
})
})
} else {
this.massages.push({
id: doc.id,
title: doc.data().title,
shortDescription: doc.data().shortDescription,
})
}
// end pertinent change
})
})
} catch (e) {
console.log(e)
}
}

How to add data stored in one variable to another data field inside data return in Nuxt?

I am trying to add Full Calendar to my Nuxt project. Here is my code.
<template>
<div>
<!-- {{calendarOptions}} -->
<FullCalendar :options="calendarOptions" />
</div>
</template>
<script>
import FullCalendar from '#fullcalendar/vue'
import dayGridPlugin from '#fullcalendar/daygrid'
import interactionPlugin from '#fullcalendar/interaction'
import timeGridPlugin from '#fullcalendar/timegrid'
export default {
components: {
FullCalendar, // make the <FullCalendar> tag available
},
data() {
return {
allevents: [{ title: 'Event 2', start: '2021-01-04', end: '2021-01-07' },
{ title: 'Event 3', start: '2021-01-05', end: '2021-01-09' }],
calendarOptions: {
plugins: [dayGridPlugin, interactionPlugin, timeGridPlugin],
initialView: 'dayGridMonth',
nowIndicator: true,
events: [
{ title: 'Event 1', start: '2021-01-01', end: '2021-01-03' },
],
},
}
},
}
</script>
I want to add data in allevents array to events array inside calenderOptions object.
Can anyone please tell me how I can do this?
Create a method to push data from your allevents array to the calendarOptions.events array.
methods: {
doTheThing() {
this.allevents.forEach(event => {
this.calendarOptions.events.push(event)
}
}
}

Vuetify dynamic data-table component

I'm quite new to Vue development and I made a dynamic list component, using Vuetify v-data-table. In this component I receive a config object as a prop and get the configuration of the headers, links for redirections and some other stuff aswell.
Now I'm stuck with a problem: I can't format my cell's content because I can't use the normal v-slot:item.<property> approach to apply the filter. Is there any way of receiving a pointer of the filter and applying it to every value at the specified column?
Thanks.
edit:
Component =>
<template>
<div class="container">
<v-app>
<v-data-table :headers="config.cabecalho" :items="data" sort-by="id" class="elevation-1">
<template v-slot:top>
<v-toolbar flat color="white">
<v-toolbar-title>{{ config.titulo }}</v-toolbar-title>
<v-divider class="mx-4" inset vertical></v-divider>
<div class="flex-grow-1"></div>
<v-dialog v-model="dialog" max-width="500px">
<template v-slot:activator="{ on }">
<v-btn color="primary" dark class="mb-2" #click="novoItem">Novo</v-btn>
</template>
</v-dialog>
</v-toolbar>
</template>
<template v-slot:item.acoes="{ item }">
<v-icon small class="mr-2" #click="editItem(item)">edit</v-icon>
<v-icon small #click="deleteItem(item)">delete</v-icon>
</template>
</v-data-table>
</v-app>
</div>
</template>
<script>
import { mapState } from 'vuex'
import axios from 'axios'
export default {
data: () => ({
dialog: false,
data: []
}),
props: {
config:{
type: Object
}
},
methods:{
editItem(item) {
return this.$router.push(this.config.linkEdit + item.id)
},
deleteItem(item) {
const index = this.data.indexOf(item)
confirm("Tem certeza que quer excluir o item?") &&
axios.get(this.config.linkDelete)
.then(res => {
if (res.status == '200') {
alert('Item excluído com sucesso.')
}
else {
alert('Falha ao excluir item, tente novamente.')
}
})
.catch( e => console.log(e))
},
novoItem () {
this.$router.push(this.config.linkNovo)
}
},
async mounted() {
await setTimeout(() => {
this.data = [
{ id: 1, numero: '1', entidade:'Cliente Um', dtIni: '2019-06-01', dtFim: '2020-06-02', vlrTotal: 3500.00, diaVenc: '5' },
{ id: 2, numero: '2', entidade:'Cliente Dois', dtIni: '2019-07-01', dtFim: '2020-07-02', vlrTotal: 7000.00, diaVenc: '15' },
{ id: 3, numero: '3', entidade:'Cliente Três', dtIni: '2019-08-01', dtFim: '2020-08-02', vlrTotal: 1200.00, diaVenc: '10' },
{ id: 4, numero: '4', entidade:'Cliente Quatro', dtIni: '2019-09-01', dtFim: '2020-09-02', vlrTotal: 800.00, diaVenc: '25' },
{ id: 5, numero: '5', entidade:'Cliente Cinco', dtIni: '2019-09-10', dtFim: '2020-09-11', vlrTotal: 25000.00, diaVenc: '5' }
]
}, 100)
},
}
</script>
Page that calls the component passing config prop =>
template>
<div class="container">
<lista-base :config="this.config"></lista-base>
</div>
</template>
<script>
import ListaBase from '~/components/padrao/ListaBase.vue'
export default {
data(){
return {
config: {
linkBusca: '',
linkNovo: '/contrato/create',
linkEdit: '',
linkDelete: '',
titulo: 'Cadastro de Contratos',
cabecalho: [
{
text: "#",
align: "right",
value: "id"
},
{
text: "Entidade",
value: "entidade",
align: "left"
},
{
text: "Início",
value: "dtIni",
align: "center"
},
{
text: "Fim",
value: "dtFim",
align: "center"
},
{
text: "Valor Total (R$)",
value: "vlrTotal",
align: "right",
filtro: "formataNumero"
},
{
text: "Ações",
value: "acoes",
sortable: false,
align: "center"
}
],
}
}
},
components: {
ListaBase
},
}
</script>
I used dummy data object because it's an experimental project still.

Resources