I must implement the library Vue-Snotify to show notifications in a Vue.js project.
Notice: I have no pre-experience with Vue.js! I just got this task and it needs to be done.
I have played around with the project and tried different approaches, which got me to understand Vue.js a bit better but after trying so much, I'm left with no idea how to fix this :(
home.js
import Snotify from 'vue-snotify'
Vue.use(Snotify)
var vmHome = new Vue({
...
components: {
myFancyComponent,
...
}
})
myFancyComponent.vue
<template>
<div>
<button type="button" #click="showNotif">Show</button>
<vue-snotify></vue-snotify>
</div>
</template>
<script>
module.exports = {
name: "my-fancy-component",
methods: {
showNotif: function() {
console.log(this.$snotify.success('Example body content'))
}
},
...
}
</script>
I can trigger the notification method and it even returns me a valid object - no errors! But no trace of a notification.
SnotifyToast {id: 338737384058, title: null, body: "Example body content", config: {…}, eventEmitter: Vue$3, …}
Though I noticed an error in the console on the page's first load:
[Vue warn]: Error in created hook: "TypeError: Cannot read property 'emitter' of undefined"
found in
---> <VueSnotify>
<MyFancyComponent>
<Root>
TypeError: Cannot read property 'emitter' of undefined
at VueComponent.created
I wonder why the VueSnotify tag wraps the MyFancyComponent and not the other way around?
It seems that you got the methods data type wrong, it needs to be an object and not array.
module.exports = {
name: "my-fancy-component",
//---------v--- This part
methods: {
showNotif: function() {
console.log(this.$snotify.success('Example body content'))
}
},
...
}
Related
I'm very new to Nuxtjs and javascript world. The Nuxtjs project I'm working on required fetching data from Backend (Strapi) using Graphql.
The goal is to make a redirect to homepage (index.vue) when Graphql return empty query result.
However, it did not work when I'm using router.push('/') as the code below.
Please note that I'm trying to redirect both on result and mounted block. Both of them did not work at all.
Please help me point out what I'm doing wrong here. Thank you for your kindness in advance
<script>
import getProfiletQuery from '~/apollo/queries/profiles/profile'
export default {
data () {
return {
profiles: {
}
}
},
apollo: {
profiles: {
prefetch: true,
query: getProfiletQuery,
variables () {
return { user: this.$route.params.user }
},
result ({ data }) {
if (data.profiles.length === 0) {
console.log('it enters here!!!')
this.$router.push('/') //this is not working
}
}
}
},
mounted () {
console.log('this.profiles.length: ', this.profiles.length)
if (this.profiles.length === 0) {
this.$router.push('/')
}
}
}
</script>
Old question, but the replies weren't helpful at all and no answers were offered. So in case you never found the answer, here's the best way I know of personally.
The reason your intended method didn't work is because it's unexpected behaviour for the Nuxt router. This is explained in much more detail here:
vue-router — Uncaught (in promise) Error: Redirected from "/login" to "/" via a navigation guard
There are some possible workarounds listed there, but don't use them in this use case.
What you want to do instead, is throw an error, then let Nuxt's built-in error handling take over.
Inside your result(), you need to properly call a Nuxt error like so:
result ({ data }) {
if (data.profiles.length === 0) {
this.$nuxt.error({ statusCode: 404, message: 'Page not found.' })
}
}
Then, you will need to ensure you have an error.vue template file inside your /layouts/ directory. This should contain at a bare minimum:
<template>
<div class="container">
<h1>{{ error.statusCode }}</h1>
<h2>{{ error.message }} </h2>
</div>
</template>
Sorry I didn't see this earlier, and hope you got something working in the meantime! At least now there is an answer there for whoever comes looking next!
Something I have never truly understood in Vue is how one should tackle the issue with undefined "network/async keys".
Give the example below:
<template>
<div>
<h1>{{row.something_undefined_before_ajax_returns.name}}</h1>
</div>
</template>
<script>
export default {
data() {
return {
row: {}
}
},
created() {
axios.get('.../row/12')
.then(response => {
// response = {data: {something_undefined_before_ajax_returns: {name: 'John Doe'}}}
this.row = response.data
})
}
}
</script>
This would return in a console warning of: [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined". However, the h1 will finally display John Doe once Vue registered the async changes.
However, the way I have coped with this 'til now is to simply define the expected key in the js like so:
<script>
export default {
data() {
return {
row: {
something_undefined_before_ajax_returns: {}
}
}
},
...
}
</script>
By doing that, Vue does not throw a warning as expected. However, this does work in the short term, but once the return data from the HTTP calls gets a bit more complex and nested, this feels really pointless having to define all the possible outcomes.
Is there a way to tell Vue to ignore such warnings until the call has been received?
You can simply use v-if:
<h1 v-if="row">{{row.something_undefined_before_ajax_returns.name}}</h1>
And you may also check row property:
<h1 v-if="row && row.something_undefined_before_ajax_returns">
{{row.something_undefined_before_ajax_returns.name}}
</h1>
Sorry, I din't notice that row is an object, to check it you may use like:
v-if="Object.keys(row).length"
But I don't think you need to check for object but its property, so you can do just:
v-if="row.something_undefined_before_ajax_returns"
I am using : Global data with VueJs 2 as my starting point as I only want to R/W one variable.
I have added an #click event to the existing code to modify the variable, but I get an "Uncaught ReferenceError: $myGlobalStuff is not defined".
Can anyone see what I am doing wrong:
HTML:
<div id="app2">
{{$myGlobalStuff.message}}
<my-fancy-component></my-fancy-component>
<button #click="updateGlobal">Update Global</button>
</div>
VueJS:
var shared = {
message: "my global message"
}
shared.install = function(){
Object.defineProperty(Vue.prototype, '$myGlobalStuff', {
get () { return shared }
})
}
Vue.use(shared);
Vue.component("my-fancy-component",{
template: "<div>My Fancy Stuff: {{$myGlobalStuff.message}}</div>"
})
new Vue({
el: "#app2",
mounted(){
console.log(this.$store)
},
methods: {
updateGlobal: function() {
$myGlobalStuff.message = "Done it!"
return
}
}
})
As you can see I am adding very little to the existing code, and that works well.
Any help on what I am overlooking would be appreciated.
Well first, the error you are getting is because you do not reference $myGlobalStuff using this. Change to this
this.$myGlobalStuff.message = "Done it!"
And you won't get the error anymore.
But I suspect it won't work the way you are expecting it to, in that, it won't be reactive. I think what you want is for the message to be updated on the page, and that is not really the intent of this code. The original point was just to supply some global values to each Vue or component.
To make it reactive we can add one change.
var shared = new Vue({data:{ message: "my global message" }})
Once you do that, message will be a reactive value.
console.clear()
var shared = new Vue({data:{ message: "my global message" }})
shared.install = function(){
Object.defineProperty(Vue.prototype, '$myGlobalStuff', {
get () { return shared }
})
}
Vue.use(shared);
Vue.component("my-fancy-component",{
template: "<div>My Fancy Stuff: {{$myGlobalStuff.message}}</div>"
})
new Vue({
el: "#app2",
mounted(){
console.log(this.$store)
},
methods: {
updateGlobal: function() {
this.$myGlobalStuff.message = "Done it!"
return
}
}
})
<script src="https://unpkg.com/vue#2.2.6/dist/vue.js"></script>
<div id="app2">
{{$myGlobalStuff.message}}
<my-fancy-component></my-fancy-component>
<button #click="updateGlobal">Update Global</button>
</div>
This is a very naive implementation of how Vuex works. The further you progress down this path, the more features of Vuex you end up implementing.
I've been following a guide to create a vue-router object, but the browser displays the following warning:
[Vue warn]: Property or method "auth_login" is not defined on the
instance but referenced during render. Make sure to declare reactive
data properties in the data option. (found in anonymous component -
use the "name" option for better debugging messages.)
I just added an event binding on a html tag, like the following:
<div id="app">
<router-view>
</router-view>
<script type="text/temptlate" id="t_auth">
<div class="auth">
<router-view></router-view>
</div>
</script>
<script type="text/temptlate" id="t_auth_login">
<div class="auth_login">
<div>
<button class="btn-primary full" id="btn_login" #click="auth_login" #keyup.enter="auth_login">登录</button>
</div>
</div>
</script>
</div>
The JS code is:
(function() {
let getView = (id) => {
tmp = document.getElementById(id)
if (tmp == null) {
return null;
}
return tmp.innerHTML
};
const routes = [{
path: '/auth',
component: { template: getView('t_auth') },
children: [
{ path: 'register', component: { template: getView('t_auth_register') } },
]
}];
const router = new VueRouter({
routes: routes
});
const app = new Vue({
router: router,
el: "#app",
data: {
name: 'Vue.js'
},
// 在 `methods` 对象中定义方法
methods: {
auth_login: function(event) {
// 方法内 `this` 指向 vm
alert('Hello ' + this.name + '!')
}
}
}).$mount('#app')
})();
Why can't it find the auth_login method? What about the lifecycle?
How can I bind the event inside the template ?
The full source code is located there: https://github.com/295421489/reminder-ximu/tree/dev/public
I don't have a direct answer for your question, but this is how you can debug your Vue apps:
Install https://github.com/vuejs/vue-devtools in your Google Chrome browser. You may need to restart the browser for the extension to start working. (I don't remember how I got it the first time)
Once you have Vue dev tools, you will start seeing this in your developer console, whenever you load a Vue app (development build of Vue.js):
Your routes will also show up very well. As you can see, my app above is currently in the route /chapter/1 (that orange box on the left side)
Click on "Send to Console" and the $vm instance will become available in your developer console.
Here, you can find if your auth_login method is available or not, for your route. And you can also do a lot more debugging for your app.
If you want a working Vue app (with routes) to test, you will find a jsFiddle in this answer: https://stackoverflow.com/a/40215123/654825
Hope it helps!
I solved this question.
The error is can't find the method,I think it is because of scope. So, I created a component firstly:
var t_auth_login = Vue.extend({
template: getView('t_auth_login'),
// 在 `methods` 对象中定义方法
methods: {
auth_login: function(event) {
}
});
and the routes values as :
const routes = [{
path: '/auth',
component: t_auth}]
everything is ok.
Im using Meteor + React and "this.props.thing.source" is a string for a mongodb _id.
The "findOne()" function is one of Meteor's. As you can see it works fine when I pass in the string of the ID itself, but I get an undefined error when passing in the variable, even though that variable renders out that same string.
In this code:
Thing = React.createClass({
propTypes: {
thing: React.PropTypes.object.isRequired
},
render() {
return (
<ul>
<li>Display: {Things.findOne(this.props.thing.source).data}</li>
<li>Display: {Things.findOne("emq6M4WbJeRvkA6Q3").data}</li>
<li>Source: {this.props.thing.source}</li>
</ul>
);
}
});
This does NOT work:
Display: {Things.findOne(this.props.thing.source).data}
This works:
Display: {Things.findOne("emq6M4WbJeRvkA6Q3").data}
And this correctly renders "emq6M4WbJeRvkA6Q3":
Source: {this.props.thing.source}
The ERROR I am getting:
"Uncaught TypeError: Cannot read property 'data' of undefined"
You're getting the error because of whatever Things.findOne() returns is undefined.
You say that calling above function with the this.props.thing.source does not work, which is wrong but since you're not mentioning how the rendering of your Thing component takes place your best bet to find the error is the way you're passing the prop this.props.thing.source/what you're passing to your component.
I made a quick copy-paste example that illustrates and also made your component work in a JSFiddle
var Things = {
findOne: function (thingSource) {
if (thingSource) {
return {
data: 'It did work!'
};
}
return undefined;
}
}
var Thing = React.createClass({
propTypes: {
thing: React.PropTypes.object.isRequired
},
render: function() {
return <div>Hello {Things.findOne(this.props.thing.source).data}</div>;
}
});
React.render(<Hello thing={{source: true}} />, document.body);
A working example with your exact component can be found here