change data value in vue component - javascript

I'm starting with vue and I'm making a test to change a value when a button is clicked , but is not working
<template>
<div class="row">
{{ show }}
<div class="col-md-4">
<button class="btn btn-primary" #click="change_show">Good</button>
</div>
<div class="col-md-4">
<button class="btn btn-primary">Bad</button>
</div>
<div class="col-md-4">
<button class="btn btn-primary">Food</button>
</div>
</div>
</template>
<script>
export default {
name: "buttons",
data(){
return{
show: true
}
},
methods:{
change_show(event){
show = !show;
}
}
}
</script>
<style scoped>
</style>
I get this error
Uncaught ReferenceError: show is not defined
How I can access to the variables and change it?

You have declared your variable incorrectly, you should add show (and all your reactive variables) in the return:
data(){
return{
show: true
};
},

Related

Cannot read properties of undefined Nuxt.js

I am trying to call the showMenu method on the click event based on the value passed on "open" variable.
But I m getting cannot read properties of undefined while, open is a defined variable.
I have tried to console log something on the click events it works, but whenever I try to interact with the open variable which is defined to the best of my knowledge I am getting the undefined error message.
<template>
<nav>
<div class="header-one">
<div class="header">
<div class="logo">Logo</div>
<div class="navigation" id="nav">
<nuxt-link to="/">Home</nuxt-link>
<nuxt-link to="/">About</nuxt-link>
<nuxt-link to="/">Login</nuxt-link>
<nuxt-link to="/">Logout</nuxt-link>
<nuxt-link to="/">Profile</nuxt-link>
</div>
**<div class="burger" id="burger" #click="showMenu">**
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<MobileMenu v-if="this.open"/>
</nav>
</template>
<script>
import MobileMenu from "~/components/MobileMenu";
export default {
name: "HeaderMenu",
MobileMenu,
data: function(){
return{
**open: false,**
}
},
methods:{
showMenu:() =>{
**this.open = !this.open**
}
}
}
</script>
This happen because your showMenu function is an arrow function wich change the scope of this.
Here this refer to the scope of the function instead of the components
Use a classic function instead
Here is an example
new Vue({
el: '#app',
data: () => {
return {
open: false
}
},
methods: {
toggleOpen1(){
this.open = !this.open
},
toggleOpen2: () => {
this.open = !this.open
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>Open : {{ open }}</div>
<button #click="toggleOpen1">Toggle open 1</button>
<button #click="toggleOpen2">Toggle open 2</button>
</div>
As you can see, the toggleOpen1 (classic function) methods work whereas the toggleOpen2 (arrow function), doesn't work.

JavaScript : this.$emit('closeRequest') is not create any event in vue dev tool

I am following a tutorial and they doing a project. everything is perfect and i was doing well. but i face an error. i have a component (Home.vue) and inside component there have a button. if user click the button then a modal will open (using BULMA scss framework and there is no js). when button is clicked then another component (Add.vue) will appear where actual modal code is writed. i pass a property Home.vue to Add.vue via <Add></Add> Component. this property value is tell modal will active or not.
here is home.vue
<template>
<div>
<nav class="panel column is-offset-2 is-8">
<p class="panel-heading">
VueJs Phonebook
<button class="button is-link is-outlined" #click="openAdd">
Add New
</button>
</p>
</nav>
<Add :openmodal='addActive'></Add>
</div>
</template>
<script>
let Add = require('./Add.vue')
export default {
components:{Add},
data(){
return{
addActive:''
}
},
methods:{
openAdd(){
this.addActive = 'is-active';
}
}
}
</script>
i am successfully get the property in Add.vue but modal has cancle and close button. i use to write a method called close. if button is clicked the this.$emit('closeRequest'); should make a event in vue dev tool. but it do not create any event if cancle or close button was clicked.
here is Add.vue file
<template>
<div class="modal" :class="openmodal">
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Modal title</p>
<button class="delete" aria-label="close" #click='close'>
</button>
</header>
<section class="modal-card-body">
<!-- Content ... -->
</section>
<footer class="modal-card-foot">
<button class="button is-success">Save changes</button>
<button class="button" #click='close'>Cancel</button>
</footer>
</div>
</div>
</template>
<script>
export default{
props:['openmodal'],
methods:{
close(){
this.$emit('closeRequest');
},
}
}
</script>
<template>
<div>
<nav class="panel column is-offset-2 is-8">
<p class="panel-heading">
VueJs Phonebook
<button class="button is-link is-outlined" #click="openAdd">
Add New
</button>
</p>
</nav>
<Add :openmodal='addActive' #closeRequest='closeAdd'></Add>
</div>
</template>
<script>
let Add = require('./Add.vue')
export default {
components:{Add},
data(){
return{
addActive:''
}
},
methods:{
openAdd(){
this.addActive = 'is-active';
},
closeAdd(){
this.addActive = '';
}
}
}
</script>

Passing functions as props to child components

Assuming I have a component named Modal which I want to reuse across my application and in the meanwhile I also want to dynamically bind functions to its Yes button, how can I pass a function to the #click event of the Yes button in my Modal as a prop. For instance:
//data tags are used for fast markup here only
<tamplate>
<div>
<div :id="`${id}`" data-modal>
<div data-modal-title>
{{title}}
</div>
<div data-modal-body>
{{body}}
</div>
<div data-modal-footer>
<button #click="//event to be passed//" data-modal-button-ok>Yes</button>
<button data-modal-button-cancel>Yes</button>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'modal',
props: [
'id',
'title',
'body',
// event?
]
}
</script>
and when using this modal, how should the event be passed?
<Modal id="x" title="y" body="x" //event="????"//></Modal>
You should $emit an event (name, say, yes) at the modal:
<button #click="$emit('yes')" data-modal-button-ok>Yes</button>
Or, use a method:
<button #click="handleYesClick" data-modal-button-ok>Yes</button>
methods: {
handleYesClick() {
this.$emit('yes');
}
}
And listen to it in the parent using:
<modal ... v-on:yes="someCodeToExecute"></modal>
or (shorthand):
<modal ... #yes="someCodeToExecute"></modal>
Demo:
Vue.component('modal', {
template: "#modal",
name: 'modal',
props: ['id', 'title', 'body']
})
new Vue({
el: '#app',
data: {},
methods: {
methodAtParentYes() {
alert('methodAtParentYes!');
},
methodAtParentCancel() {
alert('methodAtParentCancel!');
}
}
})
<script src="https://unpkg.com/vue"></script>
<template id="modal">
<div>
<div :id="`${id}`" data-modal>
<div data-modal-title>
{{title}}
</div>
<div data-modal-body>
{{body}}
</div>
<div data-modal-footer>
<button #click="$emit('yes')" data-modal-button-ok>Yes</button>
<button #click="$emit('cancel')" data-modal-button-cancel>Cancel</button>
</div>
</div>
</div>
</template>
<div id="app">
<modal id="1" title="My Title" body="Body" #yes="methodAtParentYes" #cancel="methodAtParentCancel"></modal>
</div>
There are two ways to do this.
The first way is you could pass the method down as a prop, just like you would pass anything else and then in the Modal component just call that prop right in the click handler.
Parent.vue
<template>
<Modal id="x" title="y" body="x" :handleYes="handleYes"></Modal>
</template>
<script>
methods: {
handleYes () {
// do something
}
}
</script>
Modal.vue
<button #click="handleYes()">Yes</button>
The other way is to use $emit. So in Modal.vue you would define a method to emit an event and then listen for that event in the parent and do call the method there.
Modal.vue
<template>
<button #click="emitEvent">Yes</button>
</template>
<script>
methods: {
emitEvent () {
this.$emit('userClickedYes')
}
}
</script>
Parent.vue
<template>
<Modal id="x" title="y" body="x" #userClickedYes="handleYes"></Modal>
</template>
<script>
methods: {
handleYes () {
// do something
}
}
</script>

Vue js template rendering issue

First time with vue. I am learning it playing around with some examples from Laracasts. I cannot get external template to render and the console shows cannot find element: #toolbar-chat.
My template is:
<template>
<div id="toolbar-chat">
<div class="toolbar-chat">
<ul v-for="chat in messages">
<li><b>#{{ chat.nickname }} says:</b> #{{ chat.message }}</li>
</ul>
</div>
<div class="input-group input-group-sm">
<input class="form-control" value="" placeholder="Type message..." required="required" maxlength="140" v-model="newMsg">
<div class="input-group-btn">
<button class="btn btn-primary" type="button" #click="press">
<i class="fa fa-paper-plane"></i>
</button>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
},
data() {
return {
nickname: [],
message: ''
}
},
ready() {
Echo.channel(chat_channel)
.listen('ChatMessageWasReceived', (data) => {
// Push data to messages list.
this.messages.push({
message: data.chat.message,
nickname: data.player.nickname
});
});
},
methods: {
press() {
// Send message to backend.
this.$http.post(chat_send_route, {message: this.newMsg})
.then((response) => {
// Clear input field.
this.newMsg = '';
});
}
}
};
</script>
My HTML contains the following tag:
<div class="col-xs-12 col-md-4" id="toolbarChat">
<my-chat></my-chat>
</div>
My vue component call is inside a document ready function like this:
require('./../app/bootstrap');
$(document).ready(function()
{
....
// Set up chat
Vue.component('my-chat', require('./../generic/chat.vue'));
const app = new Vue({
el: '#toolbar-chat'
});
});
And I include vue in my bootstrap file like this, then compile with webpack and no errors.
window.Vue = require('vue');
Why is my HTML template not rendering?
In your HTML you have the following div:
<div class="col-xs-12 col-md-4" id="toolbarChat">
<my-chat></my-chat>
</div>
Change it to
<div class="col-xs-12 col-md-4" id="toolbar-chat">
<my-chat></my-chat>
</div>
Because that is the id that new Vue({el: "#toolbar-chat",...}) is looking for.

Laravel+vue - Props is undefined

so I am new to vue, but getting up to speed. However, I cannot make the props thing to work - it always remains undefined in my child component.
The idea of the below is to create a app-wide notification modal window to display notifications.
This is my app.js
require('./bootstrap');
import ModalNotification from './components/Modal-Notification.vue';
const app = new Vue({
el: '#app',
data : {
formInputs: {},
formErrors: {},
showModal: false
},
components: {ModalNotification}
});
This is my Modal-Notification.vue
<template>
<transition name="modal">
<div class="modal-mask" #click="$emit('close')">
<div class="modal-wrapper">
<div class="modal-container" #click.stop>
<!-- <div class="modal-header">
<slot name="header">
NOTIFICATION
</slot>
</div> -->
<div class="modal-body">
<slot name="body">
Bla bla
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
<button class="modal-default-button btn btn-success" #click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
name: 'ModalNotification',
data: function() {
return {
};
},
props: ['showModal'],
mounted: function() {
console.log(this);
document.addEventListener("keydown", (e) => {
console.log(this.showModal);
if (this.showModal && e.keyCode == 27) {
this.$emit('close');
}
});
},
methods: {
}
}
</script>
And the relevant part of app.blade.php
<div class="container-fluid" id="app">
<button #click="showModal = true" class="btn btn-default">MODAL</button>
<modal-notification v-if="showModal" #close="showModal = false" :showModal="false">
<p slot="body" id="notification-message">hehe</p>
</modal-notification>
<div id="wrapper">
#yield('sidebar')
#yield('content')
</div>
</div>
I've tried everything out there, except switching to Browserify, babel and such stuff, but I don't think it should be needed - webpack should work just fine.
Please help, if you can.
You have mistake in the following snippet of code:
<modal-notification v-if="showModal" #close="showModal = false" :showModal="false">
<p slot="body" id="notification-message">hehe</p>
</modal-notification>
:showModal="false" is basically shortcut of v-bind:showModal="false", which tries to search vue instance variable in the value of attached HTML property(documentation). as you are passing false which is not a vue data variable, it is just passing null in showModal props.
If you want to pass only false, change the code to following:
<modal-notification v-if="showModal" #close="showModal = false" showModal="false">
<p slot="body" id="notification-message">hehe</p>
</modal-notification>
Edited
I think it is magic of camelCase-vs-kebab-case:
HTML attributes are case-insensitive, so when using non-string templates, camelCased prop names need to use their kebab-case (hyphen-delimited) equivalents:
You need to pass : show-modal="false"
<modal-notification v-if="showModal" #close="showModal = false" show-modal="false">
<p slot="body" id="notification-message">hehe</p>
</modal-notification>

Categories

Resources