I am using this library: https://github.com/cristijora/vue-notifyjs
The documentation on the above page states: component: { //is rendered instead of notification message thus I am trying to give it dynamic component so I can handle custom events. This is my code:
Vue.use(vueNotifyjs)
new Vue({
el: '#app',
methods: {
addNotification(verticalAlign = 'top', horizontalAlign = 'right') {
this.$notify({
component: function(){
return {
template: '<h1>Hello</h1>'
};
},
horizontalAlign: horizontalAlign,
verticalAlign: verticalAlign,
type: "success"
})
}
}
})
This is my jsfiddle: https://jsfiddle.net/z11fe07p/2706/
But the word Hello is not getting rendered in the notify. Any ideas what am I missing?
I think the component key should be have an instance of Vue Component.
In your scenario, create a vue component as follows
Vue.component('custom-message',{
template:`<div>Hello World</div>`
})
I have modified the fiddle with the above in this link.
Hope it helps
Related
I got a simple single-file component called "MobileApps.vue":
<template>
<div class="grey-bg about-page">
<p>{{ greetings }}</p>
</div>
</template>
<script>
export default {
name: 'Home',
data() {
return {
greetings: "Hello"
}
}
};
</script>
And registering it:
const app = new Vue({
el: '#app',
router,
components: {
Home,
About,
Gas,
Electricity,
Contacts,
Electricity_info,
Gas_info,
MobileApps
},
data: {
},
created() {
},
destroyed() {
},
mounted() {
let mySVGsToInject = document.querySelectorAll('img.inject-me');
SVGInjector(mySVGsToInject);
},
methods: {
}
});
When I'm trying to open the HTML file with <MobileApps> component I'll get an error:
vue.esm.js:628 [Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.
But even when I provide a name, nothing happens.
Try with cabeb-case format <mobile-apps> like :
<mobile-apps></mobile-apps>
Sadly I'm not that familiar with Vue and hope someone can help me a bit...
I have this in my index.html:
<xyz :isHidden="hidden">...</xyz>
Now, I have my xyz component:
Vue.component('graph', {
props: ['isHidden'],
watch: {
isHidden() {
doSomething(this.isHidden);
}, ...
}
....
}
Then, I have my Vue app:
let app = new Vue({
el: '#root',
methods: {
action() {
this.hidden = !this.hidden;
}, ...
}, ....
data: { hidden: false }
})
Now, as I understand the :hidden="isHidden" part should bind the two variable in the different part together, right? So when I change isHidden it should also change hidden and therefore call the watched function which does something. But as it turns out it doesn't.. already when my component is loaded hidden is undefined..
Did I forget something? Or is my mistake probably in the part "..." part of my code? .-.
Oh, wait.. now I feel stupid....
Well, anyone else struggling: no big letters (camelCase) in Vue-HTML..
fixed HTML:
<xyz :is-hidden="hidden">...</xyz>
the rest can stay the same..
data section should be a function:
data () {
return {
isHidden: false
}
}
you forget use components prop and tag name and component name is should be same
new Vue({
el: '#app',
components: {
'xyz': xyz,
}
})
component name
Vue.component('xyz', {
props: ['hidden'],
watch: {
hidden() {
doSomething(this.hidden);
}, ...
}
....
}
this link should help you: https://v2.vuejs.org/v2/guide/components-registration.html
After reading the vue.js docs I just jumped into components.
I want to create a custom (local) input component that emits an event to the parent on keyup, but I have two problems. (see code example at the end of the post)
[solved] 1. I already get an error when I register the child component that says
[Vue warn]: Failed to mount component: template or render function not defined.
found in
---> <InputTest>
<Root>
I guess it's a complete no-brainer, but I just don't get it.
[solved] 2. The child event doesn't even fire
Before abstracting and simplyfing the code for this question I tried to create the same behaviour with single-file (.vue) components. With SFCs the template compiles / mounts successfully, but the child component events doesn't fire. Obviously I can not tell for sure if this problem will occur in my provided example as well, but I'd guess so.
EDIT 1: Solved problem 1
My child-component should be an object instead of a vue instance. I updated the code for that. I also changed the onChange method from lambda to function, as this doesn't point to the vue instance in a lambda.
EDIT 2: Solved problem 2
There may be times when you want to listen for a native event on the root element of a component.
Apparently the native modifier can only be used on components and not on native elements. Removing the modifier fixed the problem. I changed the code accordingly.
CODE
const inputText = {
data () {
return {
model: ''
}
},
template: '<input type="text" v-model="model" #keyup="onChange">',
methods: {
onChange: function () {
this.$emit('update', this.model);
}
}
};
const app = new Vue({
el: '#app',
data () {
return {
txt: ''
}
},
methods: {
onUpdate: function(txt) {
this.txt = txt;
}
},
components: {
'input-text': inputText
}
});
<script src="https://unpkg.com/vue#2.5.13/dist/vue.js"></script>
<div id="app">
<input-text #update="onUpdate"></input-text><br>
{{ txt }}
</div>
You don't need two vue instances. You can create a component as a simple object and use it in your vue instance
const inputText = {
template: '<div> <input type="text" #keyup.native="onChange"> </div>',
methods: {
onChange: () => {
console.log('onChange');
this.$emit('update')
}
}
}
const app = new Vue({
el: '#app',
template: '<input-test #keyup.native="onKeyup" #update="onUpdate"></input-test>',
methods: {
onUpdate: () => console.log('onUpdate'),
onKeyup: () => console.log('onKeyup')
},
components: {
'input-test': inputText
}
});
<script src="https://unpkg.com/vue#2.5.13/dist/vue.js"></script>
<div id="app"></div>
In my template I have one click event
<span v-on:click="showGalery()">
And I am using one method for it
export default {
name: 'osaka',
data: function () {
return {
galery: false,
}
},
methods: {
showGalery () {
this.galery = true
}
}
}
Is it possible to trigger this method from App.vue template where is my nav and router links is located?
I am using vue-webpack template.
I have components, router.js, App.js and main.js structure.
Remember Vue has a one way data flow, so if you want to set something on the component you can simply pass a prop and use a watcher to trigger the change:
Vue.component('gallery', {
template: `<div v-show="gallery">Gallery</div>`,
props: {
show: {
type: Boolean,
default: false
}
},
created() {
this.gallery = this.show;
},
watch: {
show(val) {
this.gallery = val;
}
},
data() {
return {
gallery: false
}
}
});
Then in the parent you would have:
new Vue({
el: '#app',
data: {
showGallery: false
}
});
And use the following markup:
<gallery :show="showGallery"></gallery>
See this JSFiddle: https://jsfiddle.net/yx1uq370/
Incidentally, if you just want to show hide the entire component, then you can just use v-show on the component itself which
Vue.component('gallery', {
template: `<div>Gallery</div>`
});
new Vue({
el: '#app',
data: {
showGallery: false
}
});
Then your markup:
<gallery v-show="showGallery"></gallery>
And here's the fiddle for that: https://jsfiddle.net/gfr9kmub/
One final thing, are you sure that you really need to trigger this from your nav? I would assume that your nav would display the views and the views themselves would take care of this type of state management. Otherwise you may want to look at vuex to handle this situation
It's my first post on stackoverflow, so sorry in advance if I do something incorrectly. My question;
I've setup a VueJS project, and I'm trying to reach data that I put in the App.vue from another component. To do this, I use this.$root.count for example, but it returns undefined.
Main.js:
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App'
Vue.use(VueRouter);
const router = new VueRouter({
mode: 'history',
routes: [{
path: '/',
name: 'home',
component: function (resolve) {
require(['./components/Hello.vue'], resolve)
}
}, {
path: '/race-pilot',
name: 'racePilot',
component: function (resolve) {
require(['./components/RacePilot.vue'], resolve)
}
}
});
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
});
App.vue:
<template>
<div>
<div class="menu" ref="menu">
<router-link :to="{ name: 'home' }">Home</router-link>
<router-link :to="{ name: 'racePilot' }">Race Pilot</router-link>
</div>
<div id="app">
<router-view></router-view>
</div>
</div>
</template>
<style src="./assets/css/app.scss" lang="scss"></style>
<script>
import Hello from './components/Hello'
export default {
name: 'app',
components: {
Hello
},
data () {
return {
count: '0'
}
}
}
</script>
RacePilot.vue:
<template>
<div class="race-pilot">
</div>
</template>
<script>
export default {
name: 'RacePilot',
mounted() {
console.log(this.$root.count);
}
}
</script>
So the last log returns undefined. However, if I log this.$root, I do get the object. Anybody any idea? Thanks in advance!
Vuex is fine and all, but if you just want to expose a property to all of your views in a router based app, you can set it on the router-view.
<router-view :count="count"></router-view>
Then your view component just needs to accept it as a prop.
export default {
props:["count"],
name: 'RacePilot',
mounted() {
console.log(this.count);
}
}
this.$root references the top level Vue instance (new Vue...) and not the App VueComponent.
it is really hacky, other solutions are preferable, but this could work:
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App },
methods: {
getCount() {
return this.$children[0].count
}
},
});
and using getCount() in RacePilot.vue:
export default {
name: 'RacePilot',
mounted() {
console.log(this.$root.getCount());
}
}
You are trying to access data which is stored in App.vue but this data will be local to the component and not accessible globally.
App.vue is not the root instance (referred to by $root), instead it is the first component within the root instance which is actually created at main.js. It is during this creation time, you need to pass the data which will then be exposed for all child components via $root.
Here is the relevant portion of main.js, modified accordingly :-
new Vue({
el: '#app',
data: { count: 0 },
router,
template: '<App/>',
components: { App }
});
Tip : To confirm that App.vue is indeed the first child of root instance, try comparing the references of this.$root with this.$parent. It should returntrue which means that root instance is the parent of App.vue.
References :-
https://v2.vuejs.org/v2/guide/instance.html
https://v2.vuejs.org/v2/api/#vm-root
https://v2.vuejs.org/v2/guide/components-edge-cases.html#Accessing-the-Root-Instance
It should had worked as it is, as it is working here.
However a better way to manage global variables, which are available across components should be solved by state machine. Vue has Vuex for that purpose as stated here.
You should not do it like that.
Definitely you should not try to access other components like that.
To share data between components you can either use props (one-way binding) or Vuex to make data accessible and editable from all components through store.
You can use global $store or $router if you will start your Vue app this way:
new Vue({
el: '#q-app',
router,
store
render: h => h(require('./App'))
})
Then you can access store (for state change or access state (do not mutate state this way)) - this.$store.state.yourStaneName
You can also make the App component the actual root by passing the component directly to the Vue instance, which would look something like this:
new Vue(App).$mount('#app')
You'll probably have to move the router to App.vue, but this will make sure that this.$root will resolve to your App component directly.