I'm trying to do everytime v-switch is changed, switchPackage is changed to either true or false. Nothing appears in console, when i test. Where did i go wrong?
component
<v-switch class="package-switch" v-model="switchPackage" #change="switchPackage!=switchPackage" inset>
</v-switch>
script
export default class MembershipProducts extends Vue {
#Prop() readonly products!: Object;
data() {
return {
switchPackage:false
}
};
watch() {
switchPackage:(newValue:number) => {
console.log('switch toggled to ' + newValue);
}
};
}
My guess is that the v-switch component automatically sets the v-model (switchPackage) on click but you instantly reset it back with #change="switchPackage!=switchPackage". Just remove the #change event and it should work.
Related
First of all, I am a new vuejs developer and my purpose is to get acquainted with Vue, so, not going to use any external plugins or components.
I am writing a simple alert component, which looks like this:
<Alert :show="showAlert" />
I want the show property to return back to false after 2 seconds. How can I do this from inside the component (i.e., not in the page where this component is used). I tried this:
import { computed } from 'vue';
export default {
props: ['show'],
setup(props) {
const shown = computed(() => {
if (props.show) {
setTimeout(() => {
console.log("hiding the alert...")
props.show = false
}, 2000);
}
return props.show.value
})
return { shown }
}
};
the compiler said:
14:15 error Unexpected timed function in computed function vue/no-async-in-computed-properties
16:19 error Unexpected mutation of "show" prop vue/no-mutating-props
My rational is that the delay of alert should be controlled by the alert component (which could be changed by a prop), but not forcing the caller to write some thing like:
function Alert(delay) {
showAlert = true
setTimeout(() => showAlert = false, delay)
}
There are 2 errors.
First vue/no-mutating-props, props are read only so you are not supposed to change it from within the component. It is still possible to change props from outside the component and pass down to it.
For this you should copy the value of props to your data()
data() {
return {
showAlert
}
}
You should be able to update showAlert with no problem.
The second error vue/no-async-in-computed-properties, you cannot write async function inside computed(), so the alternative is to use watch instead.
I am not using a prop with #emit in the correct way but I don't know how to fix it. I need to know a non-global registration way of doing this correctly (I am completely new to Vue by the way)..
Here is my html in file parent.vue:
<deleteLayoutDialog v-if"showDeleteLayoutDialog"
:layout-name="dialogNameToDelete
#confirm="removeLayout(layout-name)"
#cancel="setShowDeleteLayoutDialog(false)"/>
Here is a file child.vue where deleteLayoutDialog's prop and #emit are defined:
// html
// <script>
// import { //sth } from 'files'
// #Component({ // components })
export default class DeleteLayoutDialog extends Vue {
#Prop({required: true, type: String})
public readonly layoutName: string;
#Emit()
public confirm(layoutName: string) {
// do something
}
}
</script>
Here is my javascript (inside parent.vue) where columnLayoutName appears to have a NaN value (in chrome dev tool)
public removeLayout(columnLayoutName: string) {
if (this.columnLayout.name === columnLayoutName) {
// (this.columnLayout is defined somewhere in this code)
// do something...
}
}
How should I change my html and removeLayout so that I am using prop properly? Thank you.
You are calling removeLayout instead of passing it as an argument.
#confirm="removeLayout(layout-name)"
You are trying to do a subtraction between layout and name, which are probably undefined, so you get NaN.
Just pass the reference
#confirm="removeLayout"
I am trying to watch for vuex state changes in a vue component. (I am extending a larger project and would like to react to table rows being clicked in one component by taking some of the row information and render an image based on this.)
The state change works (I can see it in the vue developer tools), but the watch is only triggered once on initial load/hot reload. I am new to vue and vuex (and pug and ts) so I guess I am missing something basic.
I found a lot of answers here stating that one should just watch the store, obviously there is more to it. I tried several variations (directly accessing the store, importing the store module and using a computed property, none of which is working, see code below. What do I need to do to make any of the watches working?
When I click the test button I created, all information is present, too.
<template lang="pug">
div
p current image {{ imageUrl }}
el-button(plain #click="onMyButtonClick") Button
</template>
<script lang="ts">
import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
import { Getter, Action, Mutation, State } from 'vuex-class';
import { RecordModuleState } from '../store/modules/records/types';
#Component
export default class ImageViewer extends Vue {
#State('records') private records!: RecordModuleState;
onMyButtonClick (): void {
console.log('Button clicked:', this.records.currentRow)
}
get imageUrl() {
return this.records.currentRow // also tried this.$store.state.records.currentRow
}
#Watch('this.$store.state.records', { immediate:true, deep: true })
onCurrentRowChanged(val: string, oldVal: string) {
console.log('watch1', val)
}
#Watch('records', { immediate:true, deep: true })
onCurrentRowChanged2(val: string, oldVal: string) {
console.log('watch2', val)
}
#Watch('imageUrl', { immediate:true, deep: true })
onCurrentRowChanged3(val: string, oldVal: string) {
console.log('watch3', val)
}
}
</script>
Instead of using #State('records') private records!: RecordModuleState;
you should be using #Getter records.
Updating data property does not update dynamic class.
Have tried setting data property through computed value.
<div class="customize-box" v-on:click="select" v-bind:class="{active: customizeBoxVisible}"></div>
<script>
export default {
data() {
return {
isSelected: false
}
},
computed: {
customizeBoxVisible: {
get() {
return this.isSelected;
},
set(value) {
this.isSelected = value;
}
}
},
methods: {
select() {
this.isSelected = true;
}
}
}
</script>
Inspecting component data in chrome dev tools shows that customizeBoxVisible is set to true. After toggling isSelected in dev tools, class gets applied.
You are calling select method but never changing isSelected data value. The correct way to toggle isSelected value is.
methods: {
select() {
this.isSelected = !this.isSelected;
}
}
Turns out I was migrating from a jQuery to a Vue.js application and forgot to remove a click handler which removed the active class from my element. Everything works as expected.
I'm trying to get a value from a VueX store during render at the render of my component. What I see is that i firstly get the error above, and then, the value is correctly updated on the component because I think that the state is well reactive but not initialized when component is rendered.
How can i avoid this error ?
template:
<span class="kt-widget17__desc">
{{ carsNumber }}
</span>
script:
export default {
data() {
return {
carsNumber: this.currentGarage.numberOfTags
};
},
computed: {
...mapGetters(["currentGarage"]),
}
};
Error:
Property or method "carsNumber" is not defined on the instance but
referenced during render. Make sure that this property is reactive..
What I did is I created a setter and getter in computed property, in your case carsNumber instead of putting it inside the data property.
computed: {
...mapGetters(["currentGarage"]),
carsNumber: {
get(){
return this.currentGarage.numberOfTags
},
set(newVal){ // setter can be excluded if not used
// you can call this.$store.commit('yourMutation', yourValue)
}
}
}