I have a problem with Vuetify checkboxes and Vuex.
What I want: Checkboxes are not check, an when any box is checked, the person-object is pushed to the selected-array. That is how it works in the Vuetify docs.
The checkboxes are checked even though are they v-modelled to an empty arrray. The table with checkboxes are populated via a getter in a computed value and to first get data into the state, I dispatch an action in the created lifecycle.
In the beginning when I just used static data, the checkboxes and other functions worked fine, but when I started using async data from Vuex, the checkboxes started being prechecked.
If I comment out the dispatch command in the created lifecycle, the checkboxes are not prechecked. Of course the table wont have data from the getter if the state in Vuex doesnt have data. But if I go to another page where the dispatch has been issued and go back to the table page, the getter now gets the data from state and checkboxes are not prechecked.
Anyone got a clue of why this is happening?
<template>
<v-simple-table>
<template v-slot:default>
<thead>
<tr>
<th #click="selectAll">Select</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr v-for="(person, index) in getPersons" :key="index">
<td>
<v-checkbox v-model="selected" :value="person"></v-checkbox>
</td>
<td>{{ person.firstName }}</td>
</tr>
</tbody>
</template>
</v-simple-table>
</template>
<script>
export default {
created() {
this.$store.dispatch("activePersons");
},
data() {
return {
selected: []
};
},
computed: {
getPersons() {
const data = [
{
firstName: "John"
},
{
firstName: "James"
}
];
console.log(data);
let test = this.$store.getters.getList;
return test;
}
},
methods: {
selectAll() {
if (this.selected.length == this.getPersons.length) {
this.selected = [];
} else {
this.selected = this.getPersons;
}
}
}
};
</script>
<style lang="scss" scoped>
</style>
Related
I want to display my data from my Firestore but I hover on my <td> tag it shows that it gets the data but it doesn't show it.
My file to get the data from Firestore
<template>
<v-container>
<v-btn #click="back" dark>Back</v-btn>
<h1>apple</h1>
<v-simple-table>
<template v-slot:default>
<thead>
<tr>
<th class="text-left">Catogorie</th>
<th class="text-left">Product</th>
</tr>
</thead>
<tbody>
<tr v-for="addProducts in Products" :key="addProducts.id">
<td>{{addProducts.catogorie}}</td>
<td>{{addProducts.product}}</td>
</tr>
</tbody>
</template>
</v-simple-table>
</v-container>
</template>
<script>
/*eslint-disable-line*/import { db } from '../../Database';
import firebase from 'firebase';
export default {
firestore: {
Products: db.collection('Products')
},
data() {
return {
Products: []
}
},
methods: {
back() {
location.reload();
console.log(firebase.auth().currentUser)
}
},
created() {
console.log(this.Products)
}
}
</script>
FireStore
On the left side you see the td tags but shows no data. And on the right side I draw a box there you see I have 2 documents in my Firestore. I tried many diffrent things.
You cannot loop over the Documents addProducts property like that.
You need to loop over the products preferably with this naming to not cause confusion:
v-for="product in Products"
And then you can access every property of the addProducts map through product.addProducts.catogorie etc.
I'm a new Dev VUE.JS and reading a lot too about "share/pass" data to anothers components, but I'm not getting perceive this examples useful in my component.
Table.vue - Fetch API and populate a table.
File.vue - Instance Table.vue and here I'm trying to override the component variable.
Table:
<template>
<v-simple-table class="mt-5" id="tableOs" dense >
<thead>
<tr>
<th v-for="h in headers" v-bind:key="h.value">{{h.text}}</th>
</tr>
</thead>
<tbody>
<tr v-for="item in items" v-bind:key="item.id">
<td>{{item.id}}</td>
<td>{{item.customer}}</td>
<td>{{item.neighbor}}</td>
</tr>
</tbody>
</v-simple-table>
</template>
<script>
export default {
data (){
return{
headers: [
{ text: 'Id', value: 'id' },
{ text: 'Name', value: 'customer' },
{ text: 'Neighbor', value: 'neighbor' }
],
items: this.pitems,
}
},
props:{
'pitems': []
},
async created(){
const res = await fetch(
"http://localhost:5000/buscarx/3",
{
method:"GET"
}
);
const data = await res.json()
this.items = data
}
}
</script>
and my Files.vue
<template>
<v-container
id="dashboard"
fluid
tag="section"
>
<v-btn #click="modify()"> </btn>
<TableOS />
</v-container>
</template>
<script>
export default {
components:{
Table: () => import('./components/Table')
},
methods:{
modify(){
console.log(this.item)
}
}
}
</script>
Anyone can me help, suggest the best way to use this fetch and modify the data in the table to use a Filter for example in the future?
You can use props to pass variables from one component to another.
For example, you need to fetch your items data in the created hook inside File.vue. Save the fetched items in items array.
Then, you can pass this items array via prop to the Table.vue component.
You can modify, filter, map and perform other tasks to the items array in the File.vue. The changes will be reactive and automatically reflect in the Table.vue file.
You can also share variables between components using vuex. But, in case of variable sharing between child and parent, like in your case, you don't need this. But if the relation between components is not so simple or they are not related you have to use vuex.
Good day developers ... I'm trying to fill a data table dynamically using information already fetched through a fetch and previously stored in a variable in my vuex instance and now called as computed property in my applets say I have this:
<script>
import { mapActions, mapGetters } from "vuex";
export default {
name: "Games",
data() {
return {
search: "",
headers:[
{text:'Game#', value:'Game#'},
{text:'Players in Game',value:'Players inGame'},
{text:'Permissions',value:'Permissions'},
{text:'Results',value:'Results'},
],
};
},
components: {
},
props: ["gameid"],
methods: {
...mapActions(["fetchingJsonEvents", "joinToGame","logOut", "createGame"]),
},
computed: {
...mapGetters(["getGamesAll", "getUserLogged"]),
getGamesAll(){
return this.$store.getters.getGamesAll.games-------->here is where the json is stored
}
},
created() {
this.fetchingJsonEvents();
}
};
</script>
and my html tag calling this computed and all else is like this:
<v-data-table :search="search" :headers="headers" v-bind:items="getGamesAll">
<template>
<tbody>
<tr v-for="(general, index) in getGamesAll.games" v-bind:key="index">
<td>Game {{general.id}}:</td>
<td>xxxxxxxx</td>
<td>xxxxxxxx</td>
</tbody>
</template>
</v-data-table>
but the table doesn't show any result , it worked with a v-simple-table, but once i try to do it in this way it doesn't....
Any advice .....thanks in advance
this is unnecessary:
getGamesAll(){
return this.$store.getters.getGamesAll.games
}
because you already have it using mapGetters:
...mapGetters(["getGamesAll", "getUserLogged"]),
if your getter getGamesAll have data then this should simply work:
<tr v-for="(general, index) in getGamesAll.games" v-bind:key="index">
Scenario:
A statistics view on a website that has to render three different data tables, one at a time.
Code:
The view is a component and inside of it i have three buttons, each one sets a variable that renders a component with a table, depending on that variable value, the table hast to call an api with different information.
the structure is as follows:
statistics component:
<template>
<div class="buttons">
<div #click="setStatisticSection('POSITIONS')">POSITIONS</div>
<div #click="setStatisticSection('RESULTS')">RESULS</div>
<div #click="setStatisticSection('FIXTURE')"">FIXTURE</div>
</div>
<data-table v-if="activeStatistic === 'FIXTURE'" data="fixture" environment="view" :loading="loading"></data-table>
<data-table v-if="activeStatistic === 'RESULTS'" data="results" environment="view"></data-table>
<data-table v-if="activeStatistic === 'POSITIONS'" data="positions" environment="view"></data-table>
</template>
<script>
import dataTable from '#/components/Table.vue';
export default {
components: {
'data-table' : dataTable,
},
data() {
return {
activeStatistic: 'RESULTS',
}
},
methods: {
setStatisticSection(section) {
this.activeStatistic = section;
}
},
}
</script>
table component:
<template>
<div>
<table class="table__fixture">
<thead>
<tr>
<td>FECHA</td>
<td>HORA</td>
<td>CONF</td>
</tr>
</thead>
<tbody>
<tr v-if="tableData.data" v-for="row in tableData.data" :key="row.id">
<td>{{row.fecha | date}}</td>
<td>{{row.fecha | time}}</td>
<td>{{row.zona}}</td>
</tr>
</tbody>
</table>
<table class="table__postions">
<thead>
<tr>
<td>POSICIÓN</td>
<td>PTS</td>
<td>ARR</td>
</tr>
</thead>
<tbody>
<tr v-if="tableData.data" v-for="row in tableData.data" :key="row.id">
<td>{{row.posicion}}</td>
<td>{{row.arrastre}}</td>
<td>{{row.pj}}</td>
</tr>
</tbody>
</table>
<table class="table__results">
<thead>
<tr>
<td>FECHA</td>
<td>HORA</td>
<td>CONF</td>
</tr>
</thead>
<tbody>
<tr v-if="tableData.data" v-for="row in tableData.data" :key="row.id">
<td>{{row.fecha | date}}</td>
<td>{{row.fecha | time}}</td>
<td>{{row.zona}}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import axios from 'axios';
export default {
props: ['data', 'environment'],
data() {
return {
tableData: '',
};
},
mounted() {
if (this.data === 'fixture' && this.environment === 'view') {
this.fetch('fixture', 1, 15);
} else if (this.data === 'positions') {
this.fetch('positions', 1, 100);
} else if (this.data === 'results') {
this.fetch('results', 1, 15);
}
},
methods: {
async fetch(data, page, perPage) {
console.log('Fire!');
const thiss = this
if (data === 'fixture') {
try {
const response = await axios.get(`apilinkhere/public/fixture?page=${page}&per_page=${perPage}`);
thiss.tableData = response.data;
} catch (e) {
throw new Error(e);
}
} else if (data === 'positions') {
try {
const response = await axios.get(`apilinkhere/positions?page=${page}&per_page=${perPage}`);
thiss.tableData = response.data;
} catch (e) {
throw new Error(e);
}
} else if (data === 'results') {
try {
const response = await axios.get(`apilinkhere/public/results?page=${page}&per_page=${perPage}`);
thiss.tableData = response.data;
} catch (e) {
throw new Error(e);
}
}
},
},
};
</script>
Problem:
The case is that the mounted hook only fires on the first component render, and not on each render (say when i change the activeStatistic) and if i put the method to call the api to for a different table data on the Updated hook, as it explains on the documentation, it drives to an infinite method call chain.
Vue documentation says that i would watch for a variable to perform this, but i'm not really sure how to do that or where to watch this variable from.
IMPORTANT:
You may see some inconsitencies on the code i show (filters applied to variables in the template that doesnt exist on the script, for example) this is because i cleaned the code i copypasted a little bit for the sake of readability, it doen't affect the problem or the information you need to offer a solution. if you see some language inconsistencies, it is due to the fact that the original code has some words in spanish.
Solution:
i simply added a watcher to the "data" prop
I have a main component called App.vue and a child one MyTable.vue which wraps a table of data and showing only the 10 first rows, i'm working with vue cli 3 and when i ran the npm run serve command and go to the given address, it renders only the head of my table, but when i add some code in the mounted() function inside MyTable.vue like console.log() it renders also the body of my table, the problem comes back when i refresh my page, how can i deal with that ?
these is my components
App.vue
<template>
<div class="main-page">
<my-table title="todos" :cols="todo_attr" :rows_data="todo_data"></my-table>
</div>
</template>
<script>
import MyTable from './components/MyTable.vue'
import todos from './assets/todos.json'
export default {
name: 'app',
data(){
return{
todo_attr:[
"todoId","id","title","completed"
],
todo_data:[]
}
},
components: {
MyTable
},
mounted(){this.todo_data=todos;}
}
</script>
MyTable.vue
<template>
<div class="vet-container">
<table>
<thead>
<th class="tab-head-cell" v-for="col in cols" :key="col">{{col}}</th>
</thead>
<tbody>
<tr class="tab-rows_data-row" v-for="row in currentPageData" :key="row.id">
<td class="tab-rows_data-cell" v-for="(cell,key,index) in row" :key="key+index" > {{cell}}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
name: 'my-table',
props: {
title: String,
cols: {},
rows_data: {}
},
data() {
return {
currentPageData: {}
};
},
methods:{
createFirstPage(){
this.currentPageData = this.rows_data.slice(0, 10);
}
}
,
mounted() {
this.createFirstPage();
}
}
</script>
First, you declared cols and rows_data as objects in MyTable.vue but you declared them as arrays in App.vue. You also declared currentPageData as an object instead of an array. It may cause some errors.
Second, you should prefer do this:
<template>
<div class="vet-container">
<table>
<thead>
<th class="tab-head-cell" v-for="col in cols" :key="col">{{col}}</th>
</thead>
<tbody>
<tr class="tab-rows_data-row" v-for="row in currentPageData" :key="row.id">
<td
class="tab-rows_data-cell"
v-for="(cell,key,index) in row"
:key="key+index" >{{cell}}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
name: 'my-table',
props: {
title: String,
cols: Array,
rows_data: Array,
},
data() {
return {
index: 0,
size: 10,
};
},
computed: {
currentPageData() {
const start = this.index * this.size;
const end = start + this.size;
return this.rows_data.slice(start, end);
},
},
};
</script>
You could then pass index in props and change it on parent on click on buttons.
Little explanation of the computed property: this property act like calculated data. You can use it just like any other data or props and you can calculate its content based on other stuff, like here, with the current index and the size of page.