vue-emoji-picker : import const from vuex module not yielding desired result - vue.js

I am trying to add custom emoji set to vue-emoji-picker
based https://codepen.io/DCzajkowski/pen/gObWjEQ
I have implemented this with partial success. I get everything loaded, except "RECENT" not added to the emoji list. Any help is greatly appreciated.
//my store/index.js
import recentEmojis from "./modules/recentEmojis";
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
recentEmojis,
},
// store/modules/recentEmojis/index.js
export const defaultEmojis = {
"Frequently used": {
thumbs_up: "+1",
red_hreat: "heart",
},
People: {
},
Nature: {
},
Objects: {
},
Places: {
},
Symbols: {
},};
const getName = (emoji) => {
console.log("getName");
const emojiMap = Object.values(defaultEmojis).reduce(
(a, b) => ({ ...a, ...b }),
{});
const object = Object.entries(emojiMap).find(
// eslint-disable-next-line no-unused-vars
([_name, value]) => value === emoji
);
return object ? object[0] : null;
};
export default {
namespaced: true,
defaultEmojis,
state: {
recentlyUsedEmojis: [],
},
mutations: {
recentlyUsedEmojis: (state, recentlyUsedEmojis) =>
(state.recentlyUsedEmojis = recentlyUsedEmojis),
},
actions: {
addEmojiToRecent: ({ state, commit }, emoji) => {
const name = getName(emoji);
const rest = state.recentlyUsedEmojis
.map(
// eslint-disable-next-line no-unused-vars
([_name, value]) => value
)
.includes(emoji)
? state.recentlyUsedEmojis.filter(
// eslint-disable-next-line no-unused-vars
([_name, value]) => value !== emoji
)
: state.recentlyUsedEmojis.length > 5
? state.recentlyUsedEmojis.slice(0, -1)
: state.recentlyUsedEmojis;
commit("recentlyUsedEmojis", [[name, emoji], ...rest])},},
getters: {
recentlyUsedEmojis: (state) =>
state.recentlyUsedEmojis.length
? { Recent: Object.fromEntries(state.recentlyUsedEmojis) }
: {},
},
}
//in my vue instance # src/pages/edtor.default.vue
...
<emoji-picker :emoji-table="emojis" #emoji="append" :search="search">
....
<script> import axios from "axios";
import EmojiPicker from "vue-emoji-picker"
import { defaultEmojis } from "../../store/modules/recentEmojis/index.js" // <<<<
export default { name: "ABCD", components: { EmojiPicker, },
...
computed: { emojis()
{ return { ...this.$store.getters.recentlyUsedEmojis, ...defaultEmojis } }, },
......
methods: {
append(emoji)
{ this.input += emoji this.$store.dispatch("recentEmojis/addEmojiToRecent", emoji) },
}

replaced
...this.$store.getters.recentlyUsedEmojis,
with
...this.$store.getters['recentEmojis/recentlyUsedEmojis']

Related

How to get module state props as single computed props (not as props of an object) from Vuex?

I have a state with single module:
const charactersModule = {
state: () => ({
characters: [],
isLoading: false,
totalPages: 0,
currentPage: 1,
itemsPerPage: ITEMS_PER_PAGE,
}),
getters: {},
mutations: {},
actions: {
async getCharacters({state}, page = state.currentPage) {
try {
state.isLoading = true;
const res = await fetch(`${BASE_URL}character/?page=${page}`);
if (res.ok) {
const { info, results } = await res.json();
state.characters = results;
}
} catch (e) {
console.log(e);
} finally {
state.isLoading = false;
}
},
},
};
export default createStore({
modules: {
characters: charactersModule,
},
});
Then in SFC:
// some component
...
methods: {
...mapActions(['getCharacters']),
}
computed: {
...mapState(['characters'])
},
mounted() {
this.getCharacters()
},
I expect that inside this SFC I can access computed properties: characters, isLoading, totalPapges, currentPage and itemsPerPage. What I actually get from ...mapState(['characters']) is an object with all this props, but I need to get them as single computed props (not as part of an object). How can I do this?
Try to use createNamespacedHelpers help to get your state with prefixing them by the module name:
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('characters')
...
methods: {
...mapActions(['getCharacters']),
}
computed: {
...mapState(['characters'])
},
mounted() {
this.getCharacters()
},

global store plugin error with vue 3 condition

With vue 3, I have state actions in different files globally, but they do not perform the necessary checks in the vue connector. I don't understand where I am doing wrong. I will be happy if you help.
I am waiting for your help to see the mistakes I have made. I am open to any comments.
app.js
require('./bootstrap');
import {createApp} from 'vue';
import App from './App.vue'
import WebsiteRouter from './Website/router';
import AdminRouter from './Admin/router';
import ApplicationRouter from './Application/router';
import store from './store';
axios.defaults.withCredentials = true;
store.dispatch('getUser').then(() => {
createApp(App)
.use(chanceRoute())
.use(store)
.use(DashboardPlugin)
.mount("#app");
})
import { createStore } from 'vuex'
import app from './app'
import appConfig from './app-config'
export default new createStore({
modules: {
app,
appConfig,
}
})
app\index.js
import axios from 'axios';
import sharedMutations from 'vuex-shared-mutations';
export default {
state: {
user: null
},
getters: {
user(state) {
return state.user;
},
verified(state) {
if (state.user) return state.user.email_verified_at
return null
},
id(state) {
if (state.user) return state.user.id
return null
}
},
mutations: {
setUser(state, payload) {
state.user = payload;
}
},
actions: {
async login({dispatch}, payload) {
try {
await axios.get('/sanctum/csrf-cookie');
await axios.post('/api/login', payload).then((res) => {
return dispatch('getUser');
}).catch((err) => {
throw err.response
});
} catch (e) {
throw e
}
},
async register({dispatch}, payload) {
try {
await axios.post('/api/register', payload).then((res) => {
return dispatch('login', {'email': payload.email, 'password': payload.password})
}).catch((err) => {
throw(err.response)
})
} catch (e) {
throw (e)
}
},
async logout({commit}) {
await axios.post('/api/logout').then((res) => {
commit('setUser', null);
}).catch((err) => {
})
},
async getUser({commit}) {
await axios.get('/api/user').then((res) => {
commit('setUser', res.data);
}).catch((err) => {
})
},
async profile({commit}, payload) {
await axios.patch('/api/profile', payload).then((res) => {
commit('setUser', res.data.user);
}).catch((err) => {
throw err.response
})
},
async password({commit}, payload) {
await axios.patch('/api/password', payload).then((res) => {
}).catch((err) => {
throw err.response
})
},
async verifyResend({dispatch}, payload) {
let res = await axios.post('/api/verify-resend', payload)
if (res.status != 200) throw res
return res
},
async verifyEmail({dispatch}, payload) {
let res = await axios.post('/api/verify-email/' + payload.id + '/' + payload.hash)
if (res.status != 200) throw res
dispatch('getUser')
return res
},
},
plugins: [sharedMutations({predicate: ['setUser']})],
}
app-config\index.js
import { $themeConfig } from '../../themeConfig'
export default {
namespaced: true,
state: {
layout: {
isRTL: $themeConfig.layout.isRTL,
skin: localStorage.getItem('skin') || $themeConfig.layout.skin,
routerTransition: $themeConfig.layout.routerTransition,
type: $themeConfig.layout.type,
contentWidth: $themeConfig.layout.contentWidth,
menu: {
hidden: $themeConfig.layout.menu.hidden,
},
navbar: {
type: $themeConfig.layout.navbar.type,
backgroundColor: $themeConfig.layout.navbar.backgroundColor,
},
footer: {
type: $themeConfig.layout.footer.type,
},
},
},
getters: {},
mutations: {
TOGGLE_RTL(state) {
state.layout.isRTL = !state.layout.isRTL
document.documentElement.setAttribute('dir', state.layout.isRTL ? 'rtl' : 'ltr')
},
UPDATE_SKIN(state, skin) {
state.layout.skin = skin
// Update value in localStorage
localStorage.setItem('skin', skin)
// Update DOM for dark-layout
if (skin === 'dark') document.body.classList.add('dark-layout')
else if (document.body.className.match('dark-layout')) document.body.classList.remove('dark-layout')
},
UPDATE_ROUTER_TRANSITION(state, val) {
state.layout.routerTransition = val
},
UPDATE_LAYOUT_TYPE(state, val) {
state.layout.type = val
},
UPDATE_CONTENT_WIDTH(state, val) {
state.layout.contentWidth = val
},
UPDATE_NAV_MENU_HIDDEN(state, val) {
state.layout.menu.hidden = val
},
UPDATE_NAVBAR_CONFIG(state, obj) {
Object.assign(state.layout.navbar, obj)
},
UPDATE_FOOTER_CONFIG(state, obj) {
Object.assign(state.layout.footer, obj)
},
},
actions: {},
}

Vuex mapActions: mapper parameter must be either an Array or an Object

When I'm trying to use the "getProducts" method through mapActions i am getting the "this.getProducts" is not a function.
Basically i get the actions from my product.js. So i don't know really why the error is existing.
I hope u can help me to handle with it. :)
My component ProductList.vue:
<script>
import ProductCard from "./ProductCard.vue";
import { mapState, mapActions } from "vuex";
export default {
components: {
ProductCard
},
computed: {
//state.modulname.state.js(products state)
...mapState("product" ["products"])
},
mounted() {
this.getProducts();
},
methods: {
...mapActions("product"["getProducts"])
}
};
</script>
<style>
</style>
My product.js File:
import store from "../../store/store";
import Product from "../../apis/Product";
const state = {
product: null,
products: [],
};
const mutations = {
SET_PRODUCT(state, product) {
state.product = product;
},
SET_PRODUCTS(state, products) {
state.products = products;
},
};
const actions = {
getProduct({ commit }, productId) {
Product.show(productId).then((response) => {
commit("SET_PRODUCT", response.data);
});
},
getProducts({ commit }) {
Product.all().then((response) => {
commit("SET_PRODUCTS", response.data);
});
},
};
const getters = {
getProductID() {
return (id) => state.products.filter((product) => product.id === id);
},
};
export default {
namespaced: true,
store,
state,
mutations,
actions,
getters,
};
Try this:
...mapActions([
'product/getProducts'
])

Vuejs with namespaced modules and unknow mutation type

i have created two store modules and I did the import into main store.
When I load my drawer view, I am getting the next error.
What am I doing wrong here
error:vuex.esm.js [vuex] unknown mutation type: SET_DRAWER
//Drawer.vue
.........
computed: {
...mapState("navstore", ["barColor", "barImage"]),
drawer: {
get() {
return this.$store.state.navstore.drawer;
},
set(val) {
this.$store.commit("SET_DRAWER", val);
},
},
computedItems() {
return null;
//this.items.map(this.mapItem);
},
profile() {
return {
avatar: true,
title: "Gestan",
};
},
},
methods: {},
.........
.........
//store/index.js
import Vue from "vue";
import Vuex from "vuex";
import { default as auth } from ".auth";
import { default as navstore } from "./navStore";
Vue.use(Vuex);
export default new Vuex.Store({
modules: { auth: auth, navstore: navstore },
});
//navstore.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
const SET_BAR_IMAGE = "NAVSTORE/SET_BAR_IMAGE";
const SET_DRAWER = "NAVSTORE/SET_DRAWER";
export default {
namespaced: true,
state: {
barColor: "rgba(0, 0, 0, .8), rgba(0, 0, 0, .8)",
barImage:
"https://demos.creative-tim.com/material-dashboard/assets/img/sidebar-1.jpg",
drawer: null,
},
mutations: {
[SET_BAR_IMAGE](state, payload) {
state.barImage = payload;
},
[SET_DRAWER](state, payload) {
state.drawer = payload;
},
},
actions: {
actionSetDrawer({ commit }, payload) {
commit(SET_DRAWER, payload);
},
},
};
//auth.js
import Vue from "vue";
import Vuex from "vuex";
import * as storage from "#/store/storage";
import services from "#/services/api/AuthenticationService";
Vue.use(Vuex);
const SET_USER = "AUTH/SET_USER";
const SET_TOKEN = "AUTH/SET_TOKEN";
export default {
namespaced: true,
state: {
token: null,
user: null,
isUserLoggedIn: false,
},
mutations: {
[SET_TOKEN](state, token) {
state.token = token;
state.isUserLoggedIn = !!token;
},
[SET_USER](state, user) {
state.user = user;
},
},
getters: {
isAuthenticated: (state) => !!state.token,
// authStatus: state => state.status
},
actions: {
actionDoLogin({ dispatch }, payload) {
return services.login(payload).then((res) => {
dispatch("actionSetUser", res.data.user);
dispatch("actionSetToken", res.data.token);
});
},
};
You need to remove prefixes with slash from mutation names because your modules namespaced and you will always access this mutations outside indicating a module name like this moduleName/mutation.
For instance:
const SET_BAR_IMAGE = "NAVSTORE/SET_BAR_IMAGE";
const SET_DRAWER = "NAVSTORE/SET_DRAWER";
// should be
const SET_BAR_IMAGE = "SET_BAR_IMAGE";
const SET_DRAWER = "SET_DRAWER";
Because the SET_DRAWER mutation is inside a navspaces module you should call it indicating a module name:
this.$store.commit("navstore/SET_DRAWER", val);
Don't try to call actions inside actions like this:
actionDoLogin({ dispatch }, payload) {
return services.login(payload).then((res) => {
dispatch("actionSetUser", res.data.user);
dispatch("actionSetToken", res.data.token);
});
},
Use mutations in a desired combination:
actionDoLogin({ dispatch }, payload) {
return services.login(payload).then((res) => {
commit(SET_USER, res.data.user);
commit(SET_TOKEN, res.data.token);
});
},

Vue.js test-utils How to mock getters from module

In my ContactForm component , I have 2 computed mapGetters
computed: {
...mapGetters(["language"]),
...mapGetters("authentication", ["loading"]),
the first one is defined in my stoe/getters.js
export const language = state => {
return state.language;
};
the second one is defined in my store/modules/authentication.js
const authentication = {
namespaced: true,
getters: {
user: state => {
return state.user
},
loading: state => {
return state.loading
}
},
I am trying to mock my Vuex store , easy for the first one "language",
export const storeMock = Object.freeze({
state: {},
actions: {},
getters: {
language: () => { . // <= FINE
return "en";
},
authentication: { . // <= . WRONG
loading: () => {
return false;
}
}
}
})
but how should I mock the second one "loading" from the "authentication" module ??
If you console log the store in the app, namespaced getters have a key of namespace/getterName, so I think this should work
export const storeMock = Object.freeze({
state: {},
actions: {},
namespaced: true,
getters: {
language: () => { // <= FINE
return "en";
},
'authentication/loading' : () => {
return false;
}
}
})