How to create a reusable Vuetify Snackbar? - javascript

I'm trying to create a reusable alert/snackbar component. I declared them like this:
Snackbar.vue
<template>
<v-snackbar transition="true" timeout="2000" :show="`${show}`" :color="`${color}`" absolute top outlined right>
<strong>
{{ message }}
</strong>
</v-snackbar>
</template>
<script>
export default {
name: 'Snackbar',
props: {
show: String,
color: String,
message: String
}
}
</script>
<template>
<v-snackbar transition="true" timeout="2000" :show="`${show}`" :color="`${color}`" absolute top outlined right>
<strong>
{{ message }}
</strong>
</v-snackbar>
</template>
<script>
export default {
name: 'Snackbar',
props: {
show: String,
color: String,
message: String
}
}
</script>
I imported, and pass probs to them like so :
import Snackbar from '../../../components/Snackbar'
<Snackbar v-if="alert" color="alertColor" message="alertMessage" />
<Snackbar show="alert" color="alertColor" message="alertMessage" />
I've tried the 2 lines above, and these are the value of those 3 variables
alert = true
alertColor = green
alertMessage = create.vue?f4fe:631 DB error - insert_marketing_campaign: Duplicate entry 'TEST' for key 'MARKETING_CAMPAIGN_AK'
Result
I see no error in console, but see no snackbar either. pls help

8!
You aren't passing props values correctly, you have to do this instead:
ps. for illustration, i added an event listener(update) to deal with a close button(remove if you dont want to use)
<Snackbar :show="alert" :color="alertColor" :message="alertMessage" v-on:update="alert = $event" />
Snackbar.vue
I changed a few things here too:
the way you are using props in the attributes works, but if dont need to concatenate other values, keep it simple
prop show must be Boolean
added a beautiful button if you want to use
v-model controls snackbar exhibition, but you can't use the prop show directly on v-model, that's why we have a computed property "show2"(very creative) that read(get) the value of prop show and emit a custom event "update" if you want to change it(set)
<template>
<v-snackbar transition="true" timeout="2000" v-model="show2" :color="color" absolute top outlined right>
<strong>
{{ message }}
</strong>
<v-btn color="red" text #click="show2 = false">Close</v-btn>
</v-snackbar>
</template>
<script>
export default {
props: {
show: Boolean,
color: String,
message: String,
},
computed: {
show2: {
get() {
return this.show;
},
set(value) {
this.$emit("update", value);
},
},
},
};
</script>
Hope it helps! ;)

Check this codesandbox I made: https://codesandbox.io/s/stack-71244492-vuex-snackbar-klfunf?file=/src/store/index.js
You can set up a global snackbar in your App.vue file and update it with Vuex. In your vuex store you set up an snackbar object and create a simple update mutation and show action.
// store/index.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
snackbar: { active: false, color: "", message: "", timer: 4000 }
},
mutations: {
UPDATE_SNACKBAR(state, snackbar) {
state.snackbar = snackbar;
}
},
actions: {
showSnack({ commit }, { message, color, timer }) {
commit("UPDATE_SNACKBAR", {
active: true,
color: color,
message: message,
timer: timer
});
}
}
});
Then in your App.vue you set it up like this
<v-snackbar
v-model="snackbar.active"
:color="snackbar.color"
:right="true"
:bottom="true"
:timeout="snackbar.timer"
>
{{ snackbar.message }}
<template #action="{ attrs }">
<v-btn
color="white"
text
v-bind="attrs"
#click="snackbar.active = false"
>
Close
</v-btn>
</template>
</v-snackbar>
<script>
import { mapState } from "vuex";
export default {
name: 'App',
data: () => ({
drawer: false,
}),
computed: {
...mapState(["snackbar"])
}
}
</script>
Then you can trigger your snackbar from any component simply by doing this
// views/Home.vue
this.$store.dispatch('showSnack', {
message: 'Testing, main page.',
color: 'green darken-1'
})
// views/About.vue
this.$store.dispatch('showSnack', {
message: 'Hello from about!',
color: 'red darken-1',
timer: 2000
})

Related

Bootstrap Vue Modal Component

I'm looking to make a global Bootstrap Vue Modal component that I can use for all of my modal needs.
The issue I am facing is that it keeps giving me an error regarding prop mutation. You cannot update them directly in the child component. Which makes sense.
This is what I have so far:
<template>
<b-modal
v-model="show"
size="lg"
scrollable
centered
header-class="event-close-modal-header"
#hide="$emit('close')"
#cancel="$emit('close')"
#ok="$emit('close')"
#show="handleShow"
>
<template #modal-title="{}">
<span class="event-close-modal-header-mc2">{{ title }}</span>
</template>
<b-container fluid class="pb-4">
<h1>Content goes here</h1>
<slot />
</b-container>
</b-modal>
</template>
<script>
export default {
props: {
show: {
type: Boolean,
default: false,
required: true,
},
title: {
type: String,
required: true,
},
},
data() {
return {};
},
};
</script>
And in my parent I have something like this:
<ModalHelper
:show.sync="modalOne" // modalOne is a data property
title="One"
#close="modalOne = false"
/>
<button #click="modalOne = true">Open Modal One</button>
Error:
You can't use props in v-model. Try watch it, and copy new value into new variable in data:
data() {
return {
showModal: false
}
},
watch: {
show(newValue) {
this.showModal = newValue;
}
}
now use showModal in your code instead of "show".
However, this is no good approach.
You should open-close bootstrap vue modals using:
$bvModal.show()
$bvModal.hide()
Vue Bootstrap Modal

How do I make a state change?

I made two different components.
in one v-navigation-drawer
the second has a button that changes the States of v-navigation-drawer in vuex.
When on small screens, there is a call to v-navigation-drawer, and after clicking on the gray area, the state in vuex does not change.
enter code here
drawer.vue
<template>
<v-navigation-drawer
fixed
:value="drawer"
app
:class="getSettingsTheme"
:mini-variant="mini"
>
<b>menu</b>
</v-navigation-drawer>
</template>
sitebar.vue
<template>
<v-toolbar fixed app clipped-right :class="getSettingsTheme">
<v-tooltip right>
<v-btn slot="activator" icon #click.stop="drawerMut">
<v-icon class="theme--light grey--text" color="grey lighten-1">menu</v-icon>
</v-btn>
<span>Show/Hide drawer</span>
</v-tooltip>
</v-toolbar>
</template>
vuex
export default new Vuex.Store({
state: {
drawer: true,
},
mutations: {
drawerMut(state) {
state.drawer = !state.drawer
}
},
getters: {
drawer(state) {
return state.drawer
},
}})
You can read the drawer state from the store and update to the store
in Vue we have computed setter please go through the docs.
if you use :value then on backdrop click the state/value of the drawer won't be updated, so use v-model with drawer as computed with setter and getter.
export default {
data() {
return {
mini: true,
getSettingsTheme: ''
}
}
computed: {
drawer: {
get() {
return this.$store.getters['drawer'];
},
set(val) {
this.$store.commit('drawerMut', val);
},
}
}
}
<template>
<v-navigation-drawer fixed
v-model="drawer"
app
:class="getSettingsTheme"
:mini-variant="mini">
<b>menu</b>
</v-navigation-drawer>
</template>

ElementUI message initial render disable

been trying to use https://element.eleme.io/#/en-US/component/message
in my component via
import Message from "#/components/ElementUi/Message";
and inside that component just normal include from element-ui
<template>
<div>
<el-button :plain="true" #click="open">{{label}}</el-button>
</div>
</template>
<script>
import { Message, Button } from "element-ui";
// import lang from "element-ui/lib/locale/lang/ru-RU";
// import locale from "element-ui/lib/locale";
import "element-ui/lib/theme-chalk/index.css";
import "../../../public/css/element-variables.scss";
//locale.use(lang);
import Vue from "vue";
Vue.use(Message);
Vue.use(Button);
export default {
props: ["label", "content", "type", "duration", "run"],
data() {
return {};
},
methods: {
open() {
Message({
showClose: true,
message: this.content,
type: this.type,
duration: this.duration,
dangerouslyUseHTMLString: true
});
}
},
created() {
if (this.run == 1) {
// this.open();
}
},
beforeCreate() {}
};
</script>
What happens when my component updates this annoying message automatically display with 0 content, but I want to to be rendered only when some conditions are met
like
<div
v-if="searchCompleted.status && searchCompleted.codingType=='reverse' && searchCompleted.fullMatch == false "
>
<message
:duration="3000"
:label="'info'"
:content="'<p>No data</p>'"
:type="'message'"
></message>
</div>
</div>
The documentation lacks of information how not to show the element on initial render of component, so there must be some pure javascript option how to disable that thing and enable when needed?

vue - How a normal link could act like <route-link>?

I have two pages routed:
Home > Results
Inside 'Home', I have a button/link which is not in <route-view/> and I want this button to redirect to Results.vue passing a parameter.
This parameter named activeTab, has to open the desired vue-tabs, which I can't accomplish, because it's getting nothing from variable:
code:
Home.vue
<div class="row">
<Notes refName="Relationship" />
<Notes refName="Support" />
</div>
...
<script>
import Notes from '#/components/Monthlynotes.vue'
export default {
name: 'home',
components: {
Notes
},
</script>
/components/Monthlynotes.vue
<b-card>
<p class="card-text">{{ refName }}</p>
<b-link class="right" :activeTab="refName" href="/results">More</b-link>
</b-card>
...
<script>
export default {
props: {
refName: String,
},
</script>
Results.vue
<vue-tabs type="pills" v-model="tabName">
<v-tab title="Relationship">
<RelDT msg="Results view"/>
</v-tab>
<v-tab title="Support">
<SupDT msg="Results view"/>
</v-tab>
</vue-tabs>
...
<script>
import RelDT from '#/components/DataTable.rel.vue'
import SupDT from '#/components/DataTable.sup.vue'
export default {
name: 'results',
props: {
activeTab: String
},
components:
{
RelDT,
SupDT,
},
data() {
return {
tabName: activeTab
}
}
}
</script>
App
<router-link :to="{name:'results', param:{activeTab}}">Results</router-link>
How can I make this <b-link> route if it was a <route-link />?
Even the b-link component supports the :to property. To be found here
The value of the property will be passed to router.push().
<b-link :to="{name:'results', param:{activeTab}}">Redirect me</b-link>

How to commit mutations in a Vuex store, from a Vuetify list, VueJS

This follows on from my previous question : How to get states from a Vuex store from within a Vuetify list, VueJs
I understand how to get states from the store, but I am struggling commiting mutations from within a list.
Here is my list :
export default{
name: 'menuList',
data() {
return {
show: true,
items: [{
title: 'Do something',
icon: 'web',
event: function () {
this.$store.commit('UI/DoSomething', {
argument1: "argument1",
rootStore: this.$store
})
}
}
]
}
}
}
I have to have the event in a function as, if I don't, the commit will run straight away. I only want it to run when I click the button.
Here is my list creation :
<template>
<v-navigation-drawer v-model="show" right clipped app fixed hide-overlay permanent="true">
<v-list two-line>
<template v-for="(item, index) in items">
<v-list-tile :key="item.title" #click="item.event()">
<v-list-tile-action>
<v-icon>{{item.icon}}</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title v-html="item.title"></v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-divider :key="index"></v-divider>
</template>
</v-list>
</v-navigation-drawer>
</template>
When I wrap the commit with a function (so it doesn't execute automatically), the keyword 'this' refers to the object, not the Vue.
I'm sure I'm missing something simple here, any ideas ?
Why do you want to store a function to commit a mutation in the data option?You can just store the information needed to commit a mutation.
export default{
name: 'menuList',
data() {
return {
show: true,
items: [{
title: 'Do something',
icon: 'web',
mutation: {
type: 'UI/DoSomething',
arguments:{
argument1: "argument1",
rootStore: this.$store
}
}
}
}
]
}
}
}
Then create a method as follows
commitMutation(mutation) {
this.$store.commit(mutation.type, mutation.arguments)
}
Then add a click listener with item.mutation as an argument to commitMutation method.
#click="commitMutation(itrm.mutation)"

Categories