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
CodePudding user response:
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! ;)
CodePudding user response:
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
})