Tuesday 12 July 2022

Event Bus implementation in Vue

 In any application data sharing among various components/services are key to maintain data flow. In vue, different data sharing methods are:

  1. Props: Allow to pass data from parent to child component.
  2. Emit: Allow to pass data from child to parent component.
  3. Vuex Store: Allow to share data across components.
import mitt from 'mitt';
export default mitt();
<template>
<div class="hello">
<input v-model="message" />
<button
@click="onPublish">publish</button>
</div>
</template>
<script>
import eventbus from "@/eventbus";
export default {
name: "HelloMessagePublish",
data() {
return {
message: "",
};
},
methods: {
onPublish() {
eventbus.emit("getMessage", this.$data.message);
},
},
};
</script>
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
import eventbus from "@/eventbus";
export default {
name: "HelloMessageDisplay",
data() {
return {
msg: "",
};
},
mounted() {
eventbus.on("getMessage", (e) => {
this.$data.msg = e;
});

},
};
</script>
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
import eventbus from "@/eventbus";
export default {
name: "HelloMessageDisplay2",
data() {
return {
msg: "",
};
},
mounted() {
eventbus.on("getMessage", (e) => {
this.$data.msg = e;
});

},
};
</script>
<template>
<div id="app">
<HelloMessagePublish />
<HelloMessageDisplay />
<HelloMessageDisplay2 />

</div>
</template>
<script>
import HelloMessageDisplay from "./components/HelloMessageDisplay";
import HelloMessageDisplay2 from "./components/HelloMessageDisplay2";
import HelloMessagePublish from "./components/HelloMessagePublish";
export default {
name: "App",
components: {
HelloMessageDisplay,
HelloMessageDisplay2,
HelloMessagePublish,

},
};
</script>

Monday 4 July 2022

Custom vuex store module

 If you haven’t read through my previous article here on props vs emit in vue.js, I would recommend to read it first unless you are aware of props and emit concept of vuejs framework. I also expects, you know the basics already about Vue framework.

export default interface IUser {
firstname: string;
lastname: string;
email:string;
};
export {default as IUser} from './i-user'
// our root state is empty because we make use of modules,
// however we do need it for generic arguments and thus we declare it
export default interface IRootState { };
export { default as IRootState } from './i-root-state';
import { StoreOptions } from 'vuex';
import { IRootState } from '../interfaces';
import modules from '../modules';
const config: StoreOptions<IRootState> = {
strict: true,
state() { },
mutations: {},
actions: {},
modules,
};
export default config;
import Vue from 'vue';
import Vuex from 'vuex';
import config from './config';
import { IRootState } from './interfaces';
Vue.use(Vuex);const store = new Vuex.Store<IRootState>(config);export default store;
<template>
<div id="app">
<Home/>
<StoreData/>
</div>
</template>
<script lang="ts">
import Home from './components/Home.vue';
import StoreData from './components/StoreData.vue'
import store from "@/store";
export default {
components: {
Home,
StoreData
},
store
}
</script>
<style>
</style>
export enum GlobalUserActionEnum{
SET_USER = "setUser"
}
export default GlobalUserActionEnum;
import IUser from "@/interfaces/i-user";export enum GlobalUserGetterEnum {
GET_USER = 'getUser'
}
export default GlobalUserGetterEnum;
enum GlobalUserMutationEnum {
Mutate_USER = 'MUTATE_USER',
}
export default GlobalUserMutationEnum;
export const NAMESPACE = 'user';export default NAMESPACE;
import IUser from "@/interfaces/i-user";export type IGlobalUserPayload = Partial<IUser>;
import IUser from "@/interfaces/i-user";export default interface IUserState {
user: IUser;
};
export { default as GlobalUserActionEnum} from './global-user-action-enum';
export { default as GlobalUserMutationEnum } from './global-user-mutation-enum';
export { default as GlobalUserGetterEnum} from './global-user-getters-enum';
export { NAMESPACE } from './global-user-namespace';
export {default as IUSerState } from './i-state-user';
import IUserState from "./static/i-state-user";export const userState: () => IUserState = () => ({
user : {
firstname: '',
lastname: '',
email:''
}
});
import { MutationTree } from 'vuex';
import { GlobalUserMutationEnum } from './static';
import IUserState from "./static/i-state-user";
import { IGlobalUserPayload } from './static/global-user-payload';
export const userMutations: MutationTree<IUserState> = {
[GlobalUserMutationEnum.Mutate_USER](state, payload: IGlobalUserPayload) {
Object.assign(state.user, payload);
},

};
export default userMutations;
import { ActionTree } from 'vuex';
import { GlobalUserActionEnum, GlobalUserMutationEnum } from './static';
import IUserState from './static/i-state-user';
import { IRootState } from '../../interfaces';
import { IGlobalUserPayload } from './static/global-user-payload';
export const userActions: ActionTree<IUserState, IRootState> = {[GlobalUserActionEnum.SET_USER]({ commit }, payload: IGlobalUserPayload) {
commit(GlobalUserMutationEnum.Mutate_USER, payload);
},

};
export default userActions;
import { GetterTree } from 'vuex';
import { IRootState } from '../../interfaces';
import IUser from "@/interfaces/i-user";
import IUserState from './static/i-state-user';
import GlobalUserGetterEnum from './static/global-user-getters-enum';
export const userGetters: GetterTree<IUserState, IRootState> = {[GlobalUserGetterEnum.GET_USER](state): IUser {
return state.user;
},
};
export default userGetters;
import { Module } from 'vuex';
import { IRootState } from '../../interfaces';
import IUserState from "./static/i-state-user";
import { userGetters } from './getters';
import userMutations from './mutations';
import { userActions } from './action';
import { userState } from './state';
const globalUser: Module<IUserState, IRootState> = { namespaced: true,
state: userState,
getters: userGetters,
mutations: userMutations,
actions: userActions,

};
export default globalUser;
import user from './user'export default{
user
};
<template>
<div class="home">
First Name: <input v-model="user.firstname" />
<br />
Last Name: <input v-model="user.lastname" />
<br />
Email: <input v-model="user.email" />
<br />
<button @click="onSave()">Update User in Store</button>
<br />
</div>
</template>
<script lang="ts">
import Vue from "vue";
import { IUser } from "@/interfaces";
import { mapActions, mapGetters } from "vuex";
import {
GlobalUserActionEnum,
GlobalUserGetterEnum,
NAMESPACE,
} from "../store/modules/user/static";
export default Vue.component('Home', {

data() {
return {
user : {
firstname: "",
lastname: "",
email: "",
} as IUser,
};
},
methods:{
onSave(){
this.setUser({
firstname: this.$data.user.firstname,
lastname: this.$data.user.lastname,
email: this.$data.user.email,
}
);
alert('User details are saved to store.')
},
...mapActions(NAMESPACE, {
setUser: GlobalUserActionEnum.SET_USER,
}),
},computed:{
...mapGetters(NAMESPACE, {
getUser: GlobalUserGetterEnum.GET_USER,
}),

},
created(){
//Don
this.$data.user.firstname = this.getUser.firstname;
this.$data.user.lastname = this.getUser.lastname;
this.$data.user.email = this.getUser.email;
}
})
</script>
<template>
<div>
<br /><br />
<h1>User Data (update on click) : {{ userData }}</h1>
<h1>User Data (reactive update) : {{ userComputedData }}</h1>
<button
@click="onFetch()">Read User from Store</button>
<br />
</div>
</template>
<script lang="ts">
import Vue from "vue";
import { mapGetters } from "vuex";
import {
GlobalUserGetterEnum,
NAMESPACE,
} from "../store/modules/user/static";
export default Vue.component('StoreData', {

data() {
return {
userData: String,
};
},
methods:{
onFetch(){
this.$data.userData = this.getUser.firstname + ' ' + this.getUser.lastname + ', '+ this.getUser.email;
},

},
computed:{
...mapGetters(NAMESPACE, {
getUser: GlobalUserGetterEnum.GET_USER,
}),
userComputedData(){
return this.getUser.firstname + ' ' + this.getUser.lastname + ', '+ this.getUser.email;
}

},
created(){
this.onFetch();
}
})
</script>