In my vue app i am calling a function on click event, which is located in a component. Here is the component code:
Vue.component( 'new-board', {
template: `
<div>
<br/>
<div class="panel panel-primary">
<div class="panel-heading">
Create New Board
</div>
<div class="panel-body">
<input class="form-control" placeholder="Board Name"/>
<button
style="margin-top: 5px;"
#click.stop="addBoard"
class="btn btn-success btn-xs btn-block"
>
Add Board
</button>
</div>
</div>
</div>
`
} )
Here is the vue app instance:
var boardItem = new Vue( {
el: "#board-item",
data: {
boards: [
{ name: 'learning vue 2' }
],
newBoard: [],
viewNewBoard: true
},
methods: {
displayNewBoard: function() {
event.preventDefault()
if( this.viewNewBoard == false ) {
this.viewNewBoard = true
} else {
this.viewNewBoard = false
}
},
addBoard: function() {
console.log( 'add board' )
}
}
} )
Now, when i click on the Add Board button from the above component, it is showing this error:
Uncaught ReferenceError: addBoard is not defined
at click (eval at Xr (vue.min.js:7), :2:455)
at HTMLButtonElement.invoker (vue.min.js:6)
It seems that the button from the component can't find the addBoard method, which is written in the same file!
What i am missing here?
Try:
Vue.component( 'new-board', {
template: `
<div>
<br/>
<div class="panel panel-primary">
<div class="panel-heading">
Create New Board
</div>
<div class="panel-body">
<input class="form-control" placeholder="Board Name"/>
<button
style="margin-top: 5px;"
#click.stop="addBoard"
class="btn btn-success btn-xs btn-block"
>
Add Board
</button>
</div>
</div>
</div>
`,
methods: {
addBoard: function(){ console.log('add board');}
}
} )
A few changes here, if you want to share events with components that are not related you must use a new vue instance to fire those events and listen. So based on your code this should help.
window.Event = new Vue();
Vue.component( 'new-board', {
template: `
<div>
<br/>
<div class="panel panel-primary">
<div class="panel-heading">
Create New Board
</div>
<div class="panel-body">
<input class="form-control" placeholder="Board Name"/>
<button
style="margin-top: 5px;"
#click.stop="addBoard" // keep this as the name of the local method
class="btn btn-success btn-xs btn-block">
Add Board
</button>
</div>
</div>
</div>
`,
methods:{
addBoard(){
// fire the event, also you can add any params
Event.$emit('callAddBoard',data)
}
}
} )
And the main instance should listen to that event
var boardItem = new Vue( {
el: "#board-item",
data: {
boards: [
{ name: 'learning vue 2' }
],
newBoard: [],
viewNewBoard: true
},
methods: {
displayNewBoard: function() {
event.preventDefault()
if( this.viewNewBoard == false ) {
this.viewNewBoard = true
} else {
this.viewNewBoard = false
}
},
addBoard: function() {
console.log( 'add board' )
}
},
created(){
// here you listen and excute the remote event from component, and apply a local method.
Event.$on('callAddBoard', this.addBoard)
}
} )
As far as I tried this works , and you can send events to any component without the need of passing through the main instance.
Related
I need to make the modal visible on click, I work through components, new Vue constructs do not work
I've never worked with Vue, now I'm asking for help
Error:
64:4 error 'showModal:' is defined but never used no-unused-labels
<template>
<modalPhoto v-if="showModal == 'true'"></modalPhoto>
<div class="block-inputs">
<div class="input-header">
<h3>Photos</h3>
</div>
<div class="photos">
<div class="photo-block">
<img src="../assets/photo.jpg" class="photo modal-img" v-on:click="viewPhoto('true')">
</div>
</div>
</div>
<div class="save-changes">
<div style="margin: 0 auto;">
<button class="button-add button-save">Save</button>
</div>
</div>
<script>
import modalPhoto from './modal/modalPhoto.vue';
export default {
name: 'Photos',
data() {
showModal: false
},
methods: {
viewPhoto() {
this.showModal = true;
}
},
components: {
modalPhoto,
}
}
i new in vue.js i have test component is child and showdata component is parent my proplem is when i emit data from child to parent it is emitted successfully but when i show data in parent by #click="showusersdata1(listdata.id) i get empty data like attached image so how to show user data
here is my code
showdata.vue
<template>
<div>
id={{setUserData.id}},
name={{setUserData.name}}
email={{setUserData.email}}
<test v-on:showusersdata1="userData($event)"></test>
</div>
</template>
<script>
import MyHome from "./home";
// let Test=require('./components/test.vue').default
import test from "./test"
export default {
// components: {MyHome},
name: "showData",
data:function () {
return{
setUserData:{}
}
},
components:{
test
},
methods:{
userData:function (passedata) {
console.log(passedata)
// this.setUserData={}
this.setUserData= this.setUserData.push(passedata)
}
}
}
</script>
test.vue
<template>
<div class="row">
<div class="col-8">
<h1>this is test components1</h1>
<!-- List group -->
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Recipient's username" aria-label="Recipient's username" aria-describedby="button-addon2">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="button-addon2">Button</button>
</div>
</div>
<div class="list-group" id="myList" role="tablist">
<a v-for ="(listdata,key) in list" class="list-group-item list-group-item-action active" data-toggle="list" href="#home" role="tab">
<ul class="test">
<i class="fas fa-trash" aria-hidden="true"></i>
<i class="fas fa-edit"></i>
<i #click="showusersdata1(listdata.id)" class="fas fa-eye"></i>
</ul> {{listdata.name}}</a>
</div>
</div>
<h1>this is cchiled show data coponent</h1>
</div>
</template>
<script>
import ShowData from "./showdata";
export default {
name: "Test",
components:{
ShowData
},
data: function () {
return {
list:{},
errors:{},
}
},
mounted(){
axios.post('/getAllData')
// .then((response) =>this.list=response.data )
.then((response) =>{
this.list=response.data
} )
.catch((error) =>this.errors=error.response.data.errors )
},
methods:{
showusersdata1:function (key) {
var index = this.list.find( ({ id }) => id == key );
this.$emit('userData', index)
}
}
}
</script>
<style scoped>
.test{
float:right
}
</style>
You are emiting here:
this.$emit('userData', index)
Which means the name of your event is 'userData'. That's what you have to listen to in the parent. But if you check your parent, you are listening to the event like this:
v-on:showusersdata1="userData($event)"
This means you are trying to listen to the 'showusersdata1' event, which is not fired. You are confusing the method name in your child for your event name. Instead of what you did, you can listen to your event like this:
v-on:userData="userData"
It's also kind of a convention to name event listeners by adding "on" in front of them, example:
event name is 'userDataReceived'
event listener would be onUserDataReceived
I have 2 modal windows: register and login. When I click to "Sign Up" button, the modal window should change. What should I do?
This is a project link.
https://jsfiddle.net/Alienwave/0kqj7tr1/4/
Vue.component('signup', {
template: '#signup-template'
})
Vue.component('login', {
template: '#login-template',
data() {
return {
loginInput: '',
passwordInput: ''
}
},
methods: {
sendRequest(e) {
//code not here
},
changeModal() {
// THIS!!
}
}
});
new Vue({
el: "#app",
data() {
return {
showLogin: true,
showSignup: false
}
}
});
This is login template:
<template id="login-template">
<transition name="modal">
<div class="login-mask">
<div class="login-wrapper">
<div class="login-container">
<div class="login-footer">
<slot name="footer">
<div class="change-mode">
<button class="change-mode-reg" #click="">Sign up</button> <!-- THIS BUTTON SHOULD CHANGE MODAL! -->
</div>
</slot>
</div>
</div>
</div>
</div>
</transition>
</template>
Register template looks the same.
I cut a big chunk.
This is a good use case for Vue's custom events. I would update your code as follows:
#login-template
...
<div class="login-footer">
<slot name="footer">
<div class="change-mode">
<button class="change-mode-reg" #click="changeModal">Sign up</button>
<div class="change-mode-line"></div>
</div>
</slot>
</div>
...
login component
Vue.component('login', {
template: '#login-template',
data() {
return {
loginInput: '',
passwordInput: ''
}
},
methods: {
sendRequest(e) {
//code not here
},
changeModal() {
this.$emit('change');
}
}
});
#app
<div id="app">
<login v-if="showLogin" #close="showLogin = false" #change="changeModal"></login>
<signup v-if="showSignup" #close="showSignup = false"></signup>
</div>
Here is an updated fiddle.
(NOTE: it looks like you might have some other issues going on here, but this gets your modal switching issue fixed.)
I wanna make search feature in my website using vue js 2 and laravel. But I don't know how to make this thing works because I don't put search form in same place with template vue.
header.blade.php
<form action="javascript:void(0);" method="get">
<input type="search" placeholder="Search..." v-model="search" #keyup.enter="searchPost()" autofocus>
</form>
Home.vue
<div class="panel panel-default" v-for="post in posts">
<div class="panel-heading">
<a :href="'/' + $route.params.trans + '/post/' + post.slug"><h3>{{ post.title }}</h3></a>
<small class="date" v-if="timeLang =='en'">{{ post.created_at | formatDateEn }}</small>
<small class="date" v-else-if="timeLang =='id'">{{ post.created_at | formatDateId }}</small>
</div>
<div class="panel-body">
<img :src="'/images/post/' + post.post.image" class="img-single-page img-responsive" alt="" v-if="post.post.image">
<p>{{post.body | strip_tags | trunCate}}</p>
<a :href="'/' + $route.params.trans + '/post/' + post.slug" class="btn readmore">Read More</a>
</div>
</div>
<script>
export default {
data()
{
return {
posts: {},
}
},
created(){
this.$on('fetchdata', this.fetchPost);
},
methods: {
fetchPost() {
axios.get('/' + this.$route.params.trans + '/search?search=' + this.search)
.then(({data}) => {
this.posts = data
}
}
app.js
const app = new Vue({
el: '#app',
router,
data: {
show: false,
search: '',
}
methods: {
searchPost() {
this.$emit('fetchdata');
}
}
});
You must define the component in (by default) resources/assets/js/app.js:
Vue.component(
'search-feature',
require('./components/search-feature.vue')
);
Then you can use it anywhere in your views:
<search-feature></search-feature>
Then, once ready to test, you must compile. You can run npm run dev (or use npm run watch to watch for file changes)
This is just a basic example, of course.
Learning Vue. Trying to get a chat window div to scroll to the top when a new chat entry is found.
My Vue component is:
const app = new Vue({
el: '#toolbar-chat',
data: {
messages: []
},
created() {
this.fetchMessages();
Echo.private(chat_channel)
.listen('ChatMessageSent', (e) => {
this.messages.unshift({
message: e.data.message,
player: e.data.player.nickname
});
});
},
methods: {
fetchMessages() {
axios.get(chat_get_route)
.then(response => {
this.messages = response.data;
});
},
addMessage(message) {
this.messages.unshift(message);
this.$nextTick(() => {
this.$refs.msgContainer.scrollTop = 0;
});
axios.post(chat_send_route, message)
.then(response => {
console.log(response.data);
});
}
}
});
My chat message Template
<template>
<div ref="msgContainer" class="toolbar-chat">
<div class="row">
<div class="col-xs-12" v-for="message in messages">
<strong class="primary-font">
{{ message.player.nickname }}:
</strong>
{{ message.message }}
</div>
</div>
</div>
</template>
<script>
export default {
props: ['messages']
};
</script>
My chat send template
<template>
<div class="input-group input-group-sm">
<input id="btn-input" type="text" class="form-control" value="" required="required" maxlength="140" placeholder="Type your message here..." v-model="newMessage" #keyup.enter="sendMessage">
<div class="input-group-btn">
<button class="btn btn-primary" type="button" id="btn-chat" #click="sendMessage">
<i class="fa fa-paper-plane"></i>
</button>
</div>
</div>
</template>
<script>
export default {
props: ['player'],
data() {
return {
newMessage: ''
}
},
methods: {
sendMessage() {
this.$emit('chatmessagesent', {
player: this.player,
message: this.newMessage
});
this.newMessage = ''
}
}
}
</script>
And in my page I include the templates
<div class="col-xs-12 col-md-4" id="toolbar-chat">
<chat-messages :messages="messages"></chat-messages>
<chat-form v-on:chatmessagesent="addMessage" :player="{{ Auth::user() }}"></chat-form>
</div>
A message adds to the list OK, but I get this error:
[Vue warn]: Error in nextTick: "TypeError: Cannot set property 'scrollTop' of undefined"
Is it the way the element is named (camelCase)? What have I missed.
Since the element you want to scroll is within a component, you should implement a method on that component that you can call.
For example, in your chat-messages component...
methods: {
scrollToTop () {
this.$el.scrollTop = 0
}
}
and in your Vue instance, add a ref for that component...
<chat-messages ref="messages"...
and in the addMessage method...
this.$refs.messages.scrollToTop()
We can use scrollIntoView() method for such purpose, e.g:
this.$refs.yourRef.$el.scrollIntoView();