Vue mutating a property that is used as "v-model" - vuejs2

Many issue like this but I cannot find my way. I simplified the code to explain my problem...
Just wanted a reusable feedback message to show with the result of the rest api using vuetity andsnackbar widget.
In the parent component:
<Feedback :active="hasFeedback" :msg="feedbackMsg" />
The Feedback component:
<template>
<v-snackbar v-model="active" >
{{ msg }}
<v-icon #click="active = false">mdi-close-thick</v-icon>
</v-snackbar>
</template>
<script>
export default {
components: {},
props: ["active", "msg"]
};
</script>
I tried to add computed property, methods, getter, setter but always got an error.

Just copy your active prop to some prop in a data section of a component and use and change that prop in the data section.
<template>
<v-snackbar v-model="isActive" >
{{ msg }}
<v-icon #click="isActive = false">mdi-close-thick</v-icon>
</v-snackbar>
</template>
<script>
export default {
components: {},
props: {
active: {
type: Boolean,
default: false
}, {
msg: {
type: String
}
},
data () {
return {
isActive: this.active
}
}
};
</script>

Related

can not initialize data from prop

here is my child component:
export default {
name: "SnackBar",
props: ["show", 'msg', 'progress'],
data: () => ({
show2: this.show,
}),
}
and its template:
<template>
<div class="text-center">
<v-snackbar
v-model="this.show2"
:multi-line="true"
timeout="-1"
>
{{ msg }}
<template v-slot:action="{ attrs }">
<v-progress-circular
v-if="progress"
style="float: right"
indeterminate
color="red"/>
<v-btn
color="red"
text
v-bind="attrs"
#click="show2 = false">
Close
</v-btn>
</template>
</v-snackbar>
</div>
</template>
and I use it in the parent :
<SnackBar :show="snackbar.show" :msg="snackbar.msg" :progress="snackbar.progress"/>
the problem is that the show2 data is not defined:, here is the console log:
Property or method "show2" is not defined on the instance but referenced during render.
Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
from official docs:
The prop is used to pass in an initial value; the child component
wants to use it as a local data property afterwards. In this case,
it’s best to define a local data property that uses the prop as its
initial value:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
I am doing exactly the same thing, what is the problem?
Using the arrow function for the data property loses the vue component context, try to use a simple function :
export default {
name: "SnackBar",
props: ["show", 'msg', 'progress'],
data(){
return {show2: this.show,}
},
}
or try out this :
export default {
name: "SnackBar",
props: ["show", 'msg', 'progress'],
data: (vm) => ({
show2: vm.show,
}),
}

Vue why props is undefined on component

I try to transfer data to my component using props
If I type the name in the parent, I see that the button is working properly, ie the problem is with the component.
Where am I wrong?
Thanks in advance
Parent:
HTML
<div><button #click="changeName" :name="name">Change my name</button></div>
Script:
import UserDetail from "./UserDetail.vue";
export default {
components: {
UserDetail,
UserEdit,
},
data() {
return {
name: "Eden",
};
},
methods: {
changeName() {
this.name = "EdenM";
},
},
};
Component
<template>
<div>
<p>{{ name }}</p>
</div>
</template>
<script>
export default {
props: ["name"],
};
</script>
Ooooooh!! I add the prop an wrong place!
Here is my ans:
<user-detail :name="name"></user-detail>

Vue + Nuxt: problem passing (bind) dynamic data from parent to child component

I'm new to Vue and I'm struggling to pass dynamic data from parent to child component through props. My parent component should pass a boolean (isModalVisible) to a children component through the visible prop.
In the parent, the isModalVisible changes (from false to true) when the button is clicked.
But the child component keeps the initial value.
As far as I have understood, the data() is executed when the component is created and when any value that has been bound (visible, in this case) is changed, but this does not occurs.
Anyone can help me to find out what I am missing?
Parent component:
<template>
<div>
{{ isModalVisible }}
<CoursesModal :visible="isModalVisible" />
<button #click="showModal" title="Courses">
Courses
</button>
</div>
</template>
<script>
import CoursesModal from "../components/modals/Courses.vue";
export default {
components: {
CoursesModal
},
data() {
return {
isModalVisible: false
};
},
methods: {
showModal() {
this.isModalVisible = true;
},
closeModal() {
this.isModalVisible = false;
}
},
};
</script>
Child (modal) component:
<template>
<div>
{{ visible }}
</div>
</template>
<script>
export default {
components: {
props: {
visible: {
type: Boolean,
default: true
}
}
},
data: function() {
return {
visible: false,
};
}
};
</script>
I have tried, too, to do
return {
visible: this.visible,
};
but this value is undefined.
My package.json:
"dependencies": {
"core-js": "^3.9.1",
"nuxt": "^2.15.3"
}
I think you make a mistake about the components property. The components property did not have props property and it is used to register the component. You can read further here and here
Here is the correct way to use props:
<template>
<div>
{{ visible }}
</div>
</template>
<script>
export default {
// removed the components and data property
props: {
visible: {
type: Boolean,
default: true
}
}
};
</script>

Properly alert prop value in parent component?

I am new to Vue and have been very confused on how to approach my design. I want my component FileCreator to take optionally take the prop fileId. If it's not given a new resource will be created in the backend and the fileId will be given back. So FileCreator acts as both an editor for a new file and a creator for a new file.
App.vue
<template>
<div id="app">
<FileCreator/>
</div>
</template>
<script>
import FileCreator from './components/FileCreator.vue'
export default {
name: 'app',
components: {
FileCreator
}
}
</script>
FileCreator.vue
<template>
<div>
<FileUploader :uploadUrl="uploadUrl"/>
</div>
</template>
<script>
import FileUploader from './FileUploader.vue'
export default {
name: 'FileCreator',
components: {
FileUploader
},
props: {
fileId: Number,
},
data() {
return {
uploadUrl: null
}
},
created(){
if (!this.fileId) {
this.fileId = 5 // GETTING WARNING HERE
}
this.uploadUrl = 'http://localhost:8080/files/' + this.fileId
}
}
</script>
FileUploader.vue
<template>
<div>
<p>URL: {{ uploadUrl }}</p>
</div>
</template>
<script>
export default {
name: 'FileUploader',
props: {
uploadUrl: {type: String, required: true}
},
mounted(){
alert('Upload URL: ' + this.uploadUrl)
}
}
</script>
All this works fine but I get the warning below
Avoid mutating a prop directly since the value will be overwritten
whenever the parent component re-renders. Instead, use a data or
computed property based on the prop's value. Prop being mutated:
"fileId"
What is the proper way to do this? I guess in my situation I want the prop to be given at initialization but later be changed if needed.
OK, so short answer is that the easiest is to have the prop and data name different and pass the prop to the data like below.
export default {
name: 'FileCreator',
components: {
FileUploader
},
props: {
fileId: Number,
},
data() {
return {
fileId_: this.fileId, // HERE WE COPY prop -> data
uploadUrl: null,
}
},
created(){
if (!this.fileId_){
this.fileId_ = 45
}
this.uploadUrl = 'http://localhost:8080/files/' + this.fileId_
}
}
Unfortunately we can't use underscore as prefix for a variable name so we use it as suffix.

VueJS Passing computed data as a prop returns undefined

I've tried and tried, but i can't figure it out the problem. From what I could read elsewhere, the variable passed to the child component gets sent as undefined before the data is available in the parent.
Please see here for reference:
the code in codesandbox
<template>
<div id="app">
<child :parentData="data.message"/>
</div>
</template>
<script>
import Child from "./components/Child";
export default {
name: "App",
components: {
Child
},
computed: {
quote() { return 'Better late than never' }
},
data() {
return {
data: { message: this.quote } ,
thisWorks: { message: "You can see this message if you replace what is passed to the child" }
};
}
};
</script>
Then in the child:
<template>
<div>
<h1>I am the Child Component</h1>
<h2> {{ parentData }}</h2>
</div>
</template>
<script>
export default {
name: "Child",
props: {
parentData: { type: String, default: "I don't have parent data" },
},
};
</script>
The answer is, you cannot access the value of this.quote because at the moment the data objectis creating, the computed object actually does not exist.
This is an alternative, we will use the created() lifecycle hook to update the value of data object:
created(){
this.data = {
message: this.quote
}
},
You don't need to change any things, just adding those line of codes is enough.
I've already tested those codes in your CodeSandbox project and it works like a charm.
Hopefully it helps!