I have a problem about using prop value as a variable in VueJS. I have a component which I tranmit prop:
This is parent component:
<template>
<div class="a">
<UploadAvatarModal
apiurl="upload_avatar"
id="UploadAvatarModal"
/>
</div>
</template>
This is script of UploadAvatarModal component:
<template>
<div class="a">
...
</div>
</template>
<script>
export default {
props: {
id: String,
apiurl: String
},
methods: {
def: function () {
this.$refs.id.hide()
}
}
}
</script>
In this line: this.$refs.id.hide() How can I call methods according to prop id. Example: this.$refs.UploadAvatarModal.hide() or this.$refs.UploadAvatarModal2.hide() changed by props value??
You can access props doing :
this.propName
To access id prop you need to do :
this.id
So the line you wrote this.$refs.id.hide() should be written :
this.$refs[this.id].hide()
But it will probably do nothing as .hide() is a jquery function.
In plain javascript you would need to do :
this.$refs[this.id].style.display = 'none'
That said, it's might not be a good idea to do so.
Using vue, the best way to show/hide a component is probably to use v-if or v-show
Related
I am new to vue and I am getting this error, I am not sure if I am passing the props right and executing it well in the other component. I will explain in details what I am trying to acheive.
I am hiding a component on click on this page and showing another element on click interchangeably here.
I have read a couple of solutions but I do not understand how I'm exactly suppose to fix it
<div v-if="hidden" class="orderSummary">
<div class="orderSummary__container">
<h2 class="orderSummary__header">Order Summary</h2>
<button #click="showForm()" class="total__button">Continue</button>
<PaymentForm v-if="!hidden" :hidden="hiddenMode" />
</div>
</div>
methods: {
showForm() {
if (this.subTotal > 1) {
this.hidden = false;
}
}
},
now in the Payment Form component I need to hide the component and make the other appear also, i want to do this by passing props.
This is my code
<div class="payForm">
<div #click="hideForm()" class="PayForm__icon">
<backIcon class="icon" />
<span class="PayForm__icon-text">Go back</span>
</div>
</div>
props: ["base_amount", "value_added_tax", "hiddenMode"],
methods: {
submit() {
const data = {
name: this.name,
};
},
hideForm() {
this.hiddenMode = true;
}
},
I'm getting the error below, what do I do
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: "hiddenMode"
Don't make hiddenMode a prop; set it to state through data:
//parent
props: ["base_amount", "value_added_tax"],
data() {
return {
hiddenMode: false
}
},
...
edit:
You should also move hideForm() to the parent component and instead bind to PaymentForm's onlick:
#click="$emit('clicked')"
then in the parent component bind hideForm to the clicked emit:
<PaymentForm v-if="!hidden" :hidden="hiddenMode" #clicked="hideForm"/>
Note: the $emit doesn't have to be called "clicked" you can name it anything
First, there is a logical problem here. If hidden is false then the first DIV and children including PaymentForm are not existing.
If hidden is true the PaymentForm not showing too because you have a <PaymentForm v-if="!hidden"
Second, your PaymentForm has a hiddenMode prop and you don't set it in the parent vue. You should have :hiddenMode="hidden" and not :hidden="hiddenMode"
For you hideForm function use $emit
this.$emit('update:hiddenMode', true);
Use the .sync modifier. This way the child component does not modify the property directly. So the parent would be
<PaymentForm v-if="!hidden" :hidden-mode.sync="hiddenMode" />
and the child would be
hideForm() {
this.$emit('update:hiddenMode', true);
}
I want to store input-value from App.vue, and use it in another component. How can I do it? I don't need the show the value in the template, I just need the value inside other components function. In JS I could just use a global var, but how can I achieve it in Vue?
App.vue:
<template>
<div id='app'>
<!-- App.vue has search bar -->
<b-form-input #keydown='search' v-model='input'></b-form-input>
<div>
<!-- Here's my other components -->
<router-view />
</div>
</div>
</template>
<script>
export default {
name: 'App',
data () {
return {
input: '',
value: ''
}
},
methods: {
search () {
this.value = this.input
this.input = ''
}
}
}
</script>
Another component:
<template>
<div>
<p>I'm another component</p>
<p>App.vue input value was: {{value}} </p>
</div>
</template>
<script>
export default {
props: ['value'],
data () {
return {
value: ''
}
}
}
</script>
This is the basic logic I'm trying to achieve. Input value in App.vue --> anotherComponent.vue
If components are not parent and child you can use store for this:
More advanced vuex store that should be your default GO TO - NPM.
Or simple solution with js object.
a. Create store.js file and export object with property in which you will store value.
b. Import store.js object to vue scripts and use it simply like:
import Store from 'store.js'
Store.value
My question it's more a search for explanation.
I have two components, father and child.
Father:
<template>
<Child :data="testData" />
{{testData}} //for print data in father
</template>
<script>
export default {
name: "Father",
data() {
return {
testData: {name: "hello"}
}
}
}
</script>
And then My Child
<template>
<input v-model="data.name" />
</template>
<script>
export default {
name: "Child",
props: ["data"]
}
}
</script>
As documentation say in this section:
https://v2.vuejs.org/v2/guide/components-props.html#One-Way-Data-Flow
I expected that it will return error, but no, it's work, if I try to change input the father component show the correct new value, without console error.
So I have tested with simple string for data instead of object in father like:
Father :
<template>
<Child :data="testData" />
{{testData}} //for print data in father
</template>
<script>
export default {
name: "Father",
data() {
return {
testData: "hello"
}
}
}
</script>
Child :
<template>
<input v-model="data" />
</template>
<script>
export default {
name: "Child",
props: ["data"]
}
}
</script>
And in this case I will get the correct error:
[Vue warn]: 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: "data"
found in
Yes I know that in JS the object are different and "magic", but I expected that Vuejs not allowed this.
Is this desired/due(for JS specifics) behavior?
Thankyou.
In both exemples, your prop value is an object, or a link to an object (and its attributes/properties).
When you use v-model="data.name", you are not changing the prop, you are following the link, accessing the object, and only changing one of its attributes.
Can't say if this is bad practice, but it works great for me.
In the second exemple, the v-model="data" would actually change the link to another object, not only the prop internals.
This results in an error.
This thread can also help: https://forum.vuejs.org/t/pass-object-via-props-reference-vs-emit-value-best-practices/45683/5
I defined two different components:
'permissionTitle':customTitle,
'permissionItem':customItem,
in main template they are organized like this:
<permissionTitle content="品牌商管理">
<permissionItem>查看列表</permissionItem>
<permissionItem>添加</permissionItem>
<permissionItem>修改</permissionItem>
<permissionItem>删除</permissionItem>
</permissionTitle>
Now I want to pass values from permissionItem to permissionTitle and vice versa.
How to can I do this?
In permissionTitle.vue:
<template>
<div id="root">
<Checkbox>
<span>{{content}}</span>
</Checkbox>
<slot></slot>
</div>
</template>
In permissionItem.vue:
<template>
<Checkbox #on-change="change">
<slot></slot>
</Checkbox>
</template>
You can do this with v-model.
Add a model and prop to your child component, something like this:
Vue.component('permissionItem', {
model: {
prop: 'value',
event: 'change'
},
props: {
value: String
},
methods: {
// or however this value changes in your component
changeValue(newValue) {
this.value = value;
$emit('change', this.value;
....
And instantiate it like this:
<permissionTitle content="品牌商管理">
<permissionItem :v-model="value1">查看列表</permissionItem>
<permissionItem :v-model="value2">添加</permissionItem>
<permissionItem :v-model="value3">修改</permissionItem>
<permissionItem :v-model="value4">删除</permissionItem>
</permissionTitle>
variables 'valueN' are now available in your parent component.
Vue's documentation on this topic is a little lacking, but its basically here: https://v2.vuejs.org/v2/guide/components-custom-events.html
I have defined custom component with props. when I using this component I need dynamically bind value to on of these props
In custom component's template I have defined element like this:
<template>
...
<div class="input-group-addon" v-show="currency">{{ currency }}</div>
...
</template>
and its prop:
export default {
...
props: {
currency: {
type: String
}
}
...
}
And component's usage in another component:
component's template
<custom-component currency="calculateCurrency" ></custom-component>
component's code
export default {
components: {custom-component},
data: () => ({
myProject: null // this is used as v-model in combo box
}),
computed: {
calculateCurrency: function() {
return myProject.currency; // currency is getter in object myProject
}
}
}
so in result I have something like this:
I also tried use
suffix=calculateCurrency
without quotes but didn't help. can you help me fix it please? Thanks
I believe you are missing a colon on the binding property:
<custom-component :currency="calculateCurrency" ></custom-component>
Adding that before "currency" will allow for data-binding