After adding 1 item to TODO app fails when I just type on text field, How to fix it? - vue.js

this might be stupitest question to ask but I just can't understand why this is happening , I am trying to Build simple TODO app with Nuxt Js with Vuex, When I add one Item it works fine and displays, after that if I just type something on text field app failds and gives error
"Error: [vuex] do not mutate vuex store state outside mutation handlers."
Here is index.vue file
<template>
<v-main>
<v-row justify="center" class="py-10">
<h1 class="teal--text">NUXT TODO APP</h1>
<v-col cols="12" md="10">
<v-text-field type="text" outlined v-model="item.text"> </v-text-field>
<v-btn color="teal" x-large class="mt-3" #click="addItem">Add</v-btn>
</v-col>
<v-col cols="8">
<h1 v-if="items.length <= 0">No Data Found</h1>
<v-list v-else>
<v-list-item v-for="item in items" :key="item.id" class="my-5">
<v-list-item-content>
<v-list-item-title>{{ item.text }}</v-list-item-title>
</v-list-item-content>
<v-list-item-action class="d-flex flex-row">
<v-btn color="teal"> Edit </v-btn>
<v-btn color="error" class="mx-5"> Delete </v-btn>
</v-list-item-action>
</v-list-item>
</v-list>
</v-col>
</v-row>
</v-main>
</template>
<script>
export default {
computed: {
items() {
return this.$store.state.items;
},
},
data: () => ({
item: {
text: "",
},
}),
methods: {
addItem() {
this.$store.commit("addItem", this.item);
},
},
};
</script>
And here is index.js file for Vuex
export const state = () => ({
items: [],
});
export const mutations = {
addItem(state, payload) {
state.items.push(payload);
},
};
please guide me what the hell I am missing here.
Thank You.

Related

Imported component and console message

I have a problem with props in imported component.
I imported component with dialog template and I want display text from props and it works, but I have errors in console.
In console I see this error:
[Vue warn]: Error in render: "TypeError: Cannot read property
'test' of null"
But after open dialog value is correctly.
How can I fix this problem so that the error in console doesn't show up?
My code:
<template>
<v-container fluid>
<v-row>
<v-col cols="12">
<v-card class="">
<TipItem v-for="tip in tips" :key="tip.id" v-on:open-dialog="openTipDetailsDialog(tip)"></TipItem>
</v-card>
</v-col>
</v-row>
<TipDetailsDialog :dialog="tipDetailsDialog" :tip="tipDetails" v-on:close-dialog="tipDetailsDialog = false"></TipDetailsDialog>
</v-container>
</template>
<script>
import TipItem from "../components/TipItem";
import TipDetailsDialog from "../components/TipDetailsDialog";
export default {
name: "Tips",
components: {
TipItem,
TipDetailsDialog
},
data: () => ({
tips: [],
tipDetailsDialog: false,
tipDetails: null
}),
methods: {
openTipDetailsDialog(tip) {
this.tipDetailsDialog = true;
this.tipDetails = tip;
}
}
};
</script>
TipDetailsDialog
<template>
<v-dialog
:value="dialog"
fullscreen
hide-overlay
transition="dialog-bottom-transition"
#input="$emit('close-dialog')"
>
<v-card class="rounded-0">
<v-toolbar color="primary">
<v-toolbar-title>Szczegóły</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn icon dark #click="$emit('close-dialog')">
<v-icon>mdi-close</v-icon>
</v-btn>
</v-toolbar>
<v-container>
<v-row>
<v-col cols="6">
<v-card>
{{ tip.test }}
</v-card>
</v-col>
<v-col cols="6">
<v-card>
{{ tip.test2 }}
</v-card>
</v-col>
</v-row>
</v-container>
</v-card>
</v-dialog>
</template>
<script>
export default {
name: "TipDetailsDialog",
props: ["dialog", "tip"]
};
</script>
tipDetails is initialized as null, and then bound to <TipDetailsDialog>.tip, which causes it to try to render tip.test (where tip is null).
Since TipDetailsDialog doesn't really render anything meaningful without a populated tip, that component should probably be conditionally rendered only when tipDetails is truthy:
<TipDetailsDialog v-if="tipDetails" :tip="tipDetails" />
tipDetails is initialized as null, and then bound to
<TipDetailsDialog>.tip, which causes it to try to render tip.test
(where tip is null).
Since TipDetailsDialog doesn't really render anything meaningful
without a populated tip, that component should probably be
conditionally rendered only when tipDetails is truthy:
html <TipDetailsDialog v-if="tipDetails" :tip="tipDetails" />
Or you can set a default value to the prop:
props: {
tip: {
type: String,
required: false,
default: () => ""
},
},

Integration of Socket.IO with VUE Framework

Hello I am trying to implement socket.io with vue.js however I cannot access the emits in the different views.
After configuring main.js I can get emits on the APP, but I can't get them on HOME.
Is it possible to help with this situation.
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import vuetify from "./plugins/vuetify";
import * as io from "socket.io-client";
import VueSocketIO from "vue-socket.io";
Vue.use(
new VueSocketIO({
debug: true,
connection: io("http://localhost:3001"),
})
);
Vue.config.productionTip = false;
new Vue({
router,
store,
vuetify,
render: (h) => h(App),
}).$mount("#app");
Here I have the implementation of the first view, and here I have access to the socket.io emit!
<template>
<v-app id="inspire">
<v-app-bar app color="white" flat>
<v-container class="py-0 fill-height">
<v-avatar class="mr-10" color="grey darken-1" size="32"></v-avatar>
<v-btn v-for="link in links" :key="link" text>
{{ link }}
</v-btn>
<v-spacer></v-spacer>
<v-responsive max-width="260">
<v-switch
v-model="switchLogIn"
label="login"
color="success"
hide-details
></v-switch>
</v-responsive>
</v-container>
</v-app-bar>
<v-main class="grey lighten-3">
<v-container>
<v-row>
<v-col cols="2">
<v-sheet rounded="lg">
<v-list color="transparent">
<v-list-item v-for="n in 5" :key="n" link>
<v-list-item-content>
<v-list-item-title> List Item {{ n }} </v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-divider class="my-2"></v-divider>
<v-list-item link color="grey lighten-4">
<v-list-item-content>
<v-list-item-title to="/about">
{{ nextSip["Estado Processo"] }}
</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-sheet>
</v-col>
<v-col>
<v-alert icon="mdi-database-outline" prominent text type="info">
FILA DE TRABALHO COM {{ workFlowSize }}.
</v-alert>
<v-sheet min-height="70vh" rounded="lg" v-if="switchLogIn">
<router-view></router-view>
</v-sheet>
</v-col>
</v-row>
</v-container>
</v-main>
</v-app>
</template>
<script>
export default {
data: () => ({
links: ["Dashboard"],
switchLogIn: false,
workFlow: "",
workFlowSize: 0,
nextSip: Object,
}),
sockets: {
connect: function () {
this.$swal("Conectado com Sucesso", "Servidor Localhost:3001", "success");
console.log("socket connected");
},
workFlowSize(data) {
this.workFlowSize = data;
},
nextSip: (data) => {
console.log(data);
},
},
watch: {
switchLogIn: function (value) {
if (value == true) {
console.log("Im LOGIN");
}
},
},
};
</script>
but not here
<template>
<div class="home">
<SipForm/>
</div>
</template>
<script>
import SipForm from "#/components/SipForm.vue";
export default {
name: "Home",
components: {
SipForm,
},
data: () => ({
workFlowSize: 0,
}),
sockets: {
connect: function () {
this.$swal("Conectado com Sucesso", "Servidor Localhost:3001", "success");
console.log("socket connected");
},
workFlowSize(data) {
this.workFlowSize = data;
},
nextSip: (data) => {
console.log(data);
},
},
};
</script>

Vue, error [vuex] do not mutate vuex store state outside mutation handlers

Here is original code. Very simple, sign in form. We have Email field, password. It takes this parameters and on clicking submit button it checks the user and writes his user.uid into Vuex. But I'm getting error which is listed above in title. I did research and it looks like it's a common issue in Vuex, due to those fields at some point updating Vuex store 'on a fly' which is false in my case, cause it only updates Vuex store when you press a submit button. Anyhow decided corrected to be look like this and still have no luck
original code
<template>
<div class="form__inner">
<div class="overlay" #click="$store.commit('logReg/logIn')"></div>
<v-container
fill-height
fluid>
<v-row
align="center"
justify="center">
<v-col cols="2">
<v-card>
<v-card-title>
Log in
</v-card-title>
<v-card-text>
<v-text-field placeholder="Email"
v-model="logIn"/>
<v-text-field placeholder="Password"
v-model="password"/>
</v-card-text>
<v-card-actions>
<v-btn color="success"
class="mx-auto"
#click="signIn">Log me in</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</div>
</template>
<script>
export default {
data(){
return {
logIn: '',
password: ''
}
},
methods: {
async signIn(){
let res = await this.$fireAuth.signInWithEmailAndPassword(this.logIn, this.password);
this.$store.commit('userState', res);
}
}
}
</script>
my vuex
export const state = () => ({
user: null
})
export const mutations = {
userState(state, authUser){
state.user = authUser;
}
}
my try to fix issue which still had no luck, gives same error
<template>
<div class="form__inner">
<div class="overlay" #click="$store.commit('logReg/logIn')"></div>
<v-container
fill-height
fluid>
<v-row
align="center"
justify="center">
<v-col cols="2">
<v-card>
<v-card-title>
Log in
</v-card-title>
<v-card-text>
<v-text-field placeholder="Email"
v-model="logIn"/>
<v-text-field placeholder="Password"
v-model="password"/>
</v-card-text>
<v-card-actions>
<v-btn color="success"
class="mx-auto"
#click="signIn">Log me in</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</div>
</template>
<script>
export default {
data(){
return {
logIn: '',
password: ''
}
},
computed: {
logg: {
get(){
return this.logIn;
},
set(val){
this.logIn = val;
}
},
pass: {
get(){
return this.password;
},
set(val){
this.password = val;
}
}
},
methods: {
async signIn(){
let res = await this.$fireAuth.signInWithEmailAndPassword(this.logg, this.pass);
this.$store.commit('userState', res);
}
}
}
</script>
You have to use mutations like this:
<script>
import {mapMutations} from 'vuex';
export default {
data(){
return {
logIn: '',
password: ''
}
},
methods: {
...mapMutations({
userState: 'userState'
}),
async signIn(){
let res = await this.$fireAuth.signInWithEmailAndPassword(this.logIn,this.password);
this.userState(res);
}
}
}
</script>

Object in array is undefined in vue

I need help as the array “items1” works when “console.log(this.items1)”
However, it is undefined when “console.log(this.items1[0])”. How can I solve this? I really have no idea what is going. Ultimately, I want to gather item.text whenever user selects the tab from v-tabs. Using item.text, I am able to filter the data in db. Is there a way to gather the user input whenever user selects tab?
<template>
<v-layout>
<v-container flat grid-list-lg>
<v-layout row wrap class="flex_box feature_products">
<v-flex xs12>
<h2 class="text-xs-center feature_products_title">Check Our <span>Delicious Menu</span></h2>
</v-flex>
<v-flex xs12>
<v-card>
<v-toolbar flat>
<template v-slot:extension>
<v-tabs v-model="model" centered slider-color="yellow">
<v-tab v-for="(item, index) in items1" :key="index" :href="`#tab-${index}`">
{{ item.text }}
</v-tab>
</v-tabs>
</template>
</v-toolbar>
<v-tabs-items v-model="model">
<v-tab-item v-for="(item, index) in items1" :key="index" :value="`tab-${index}`">
<!-- your this code displays the product information, but there is no way to filter the product by category -->
<v-layout row wrap class="flex_box feature_products">
<v-flex xs12 sm3 md3 lg3 xl2 class="flex_item" v-for="(product,index) in products" :key="index">
<v-card flat v-if="product.category_name == item.text">
<v-card class="overlay_container flex_wrap pa-2">
<v-img :src="product.image" contain></v-img>
<div style="width:100%;" class="flex_bottom text-xs-center pb-2">
<h3 class="headline text-xs-center grey--text text--darken-3">{{product.item_name}}</h3>
<h4 class="grey--text text--darken-3">{{currency}}{{product.price}}</h4>
</div>
<v-card class="overlay">
<h2 style="vertical-align:middle;">{{product.item_name}}</h2>
<v-list class="details">
<v-list-tile-action>
<v-btn style="width:100%" :to="'/product/' + product.id">Details</v-btn>
</v-list-tile-action>
<v-list-tile-action>
<v-btn style="width:100%" class="main_color white--text" #click="addToCart(product)">Add To Cart</v-btn>
</v-list-tile-action>
</v-list>
</v-card>
</v-card>
</v-card>
<v-card v-else>
</v-card>
</v-flex>
</v-layout>
</v-tab-item>
</v-tabs-items>
</v-card>
</v-flex>
</v-layout>
</v-container>
</v-layout>
</template>
<script>
import Vue from 'vue'
import firebase from "firebase";
import moment from 'moment'
import db, {functions} from '#/firebase/init'
import MenuNavbar from '#/components/shop/navbar/MenuNavbar'
export default {
data(){
// Show All Categories
let ref = db.collection("item_categories");
ref.onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
if (change.type == "added") {
let doc = change.doc;
this.items1.push({
icon: doc.data().category_icon,
text: doc.data().category_name,
link:'CatProduct',
category:doc.data().category_name,
text1: 'Category Name: ' + doc.data().category_name
});
}
});
});
return{
model:'tab-2', // select your default tab here
currency:null,
products:[],
cart:this.$store.getters.cart,
items1:[],
}
},
components: {
MenuNavbar
},
methods: {
productInCart(product) {
const cartItems = this.cart
for (let i = 0; i < cartItems.length; i++) {
if (cartItems[i].product.id === product.id) {
return i
}
}
return null
},
addToCart(product, quantity){
const index = this.productInCart(product)
const productQuantity = (!quantity || quantity < 1) ? 1 : parseInt(quantity)
if (index === null) {
var items = {
product: product,
quantity: productQuantity
}
//this.$store.commit('catalog/updateCart', items)
this.$store.commit('updateCart', items)
}else {
if(!quantity){
// If item is already into the cart then add++ quantity
this.$store.commit('increaseQuantity', index)
}else{
// When quantity updated manually
}
}
},
removeCart(index){
this.$store.commit('removeCart', index)
},
},
computed:{
counter(){
return this.$store.getters.counter
},
},
getTabText(text){
return text
},
created(){
var db = firebase.firestore();
// Current Currency
db.collection("settings").doc('config').onSnapshot(doc =>{
this.currency = doc.data().currency
})
console.log(this.items1[0])
// Show All Items
let cref = db.collection('items').orderBy('timestamp', 'desc').where("featured", "==", true)
cref.onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
if(change.type == 'added'){
let doc = change.doc
this.products.push({
id:doc.id,
item_name:doc.data().item_name,
image:doc.data().image,
category_name:doc.data().item_category,
price:doc.data().price,
quantity:doc.data().quantity,
timestamp:moment(doc.data().timestamp).fromNow('lll')
})
}
})
})
}
}
</script>

How do I overcome error 'Avoid using JavaScript keyword as "v-on" value'

How do I get rid of this error in my App.vue component?
Failed to compile.
./src/App.vue
Module Error (from ./node_modules/eslint-loader/index.js):
C:\xampp2\htdocs\exchproto\src\App.vue
15:69 error Avoid using JavaScript keyword as "v-on" value: "" vue/valid-v-on
✖ 1 problem (1 error, 0 warnings)
I tested the whole code (including sub-components) with CDN pull of vuejs/vuetify css/js etc and all worked well. This error only comes up as I am breaking down the code into components and doing everything by "yarn install". Been poking at it for some time with no luck.
<template>
<v-app>
<v-app-bar app>
<v-app-bar-nav-icon #click="drawer = !drawer"></v-app-bar-nav-icon>
<v-spacer></v-spacer>
<v-menu :offset-y="true">
<template v-slot:activator="{ on }">
<v-btn icon v-on="on">
<v-icon>mdi-dots-horizontal</v-icon>
</v-btn>
</template>
<v-list>
<v-list-item v-for="(item, i) in rightMenuitems" :key="i" #click="">
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-app-bar>
<!--router-view></!--router-view-->
</v-app>
</template>
<script>
export default {
name: 'App',
components: {},
data() {
return {
drawer: false,
rightMenuitems: [
{ title: 'Choice 1' },
{ title: 'Choice 2' },
{ title: 'Choice 3' },
{ title: 'Choice 4' }
],
}
}
}
</script>
You can't have an empty #click="" You must have the click point to a function:
<v-list-item
v-for="(item, i) in rightMenuitems"
:key="i"
#click="doSomething($event, i)"
>
<v-list-item-title>
{{ item.title }}
</v-list-item-title>
</v-list-item>
// ...
methods: {
someFunction(event, i) {
console.log("clicked item " + i);
}
}
// ...
Remove 'click event' and add to property in v-list-item where v-for is being used.
Note:
You can bind links with the to props, and also links in every objects of rightMenuitems.
Here is an example: