I have a parent component that's passing a prop (selectedOption) to a child component, and the child component takes the prop and renders an icon based on the prop. But every time I load the page, the child component throws an error because the prop has not been passed down in time, but it's fine after a second when everything is passed down. How can I avoid this?
Parent (Settings.vue):
<template>
<settings-menu
:selectedOption="selectedSettingsOption">
</settings-menu>
Child (SettingsMenu.vue):
<template>
<component
:is="`icon-${ selectedOption }`">
</component>
</template>
Just put a v-if to hide the component until the prop gets passed.
<template>
<component
v-if='selectedOption' :is="`icon-${ selectedOption }`">
</component>
</template>
Related
Context -
I have a large form that I've broken up into components. I'm going to focus on only one parent/child component relationship for brevity here.
Doing some validation on each child component. Emitting back to parent when a submit button is clicked on the parent.
I have a submit button on the parent. When clicked I am emitting all child component data back to the parent
I have a method on the parent that receives the emitted data. As well as an object instantiated on the parent data() method to assign to the incoming data.
Problem -
When you hit submit, the emitted data is present on the child component, but it's empty on the parent. The submit method finishes before the emitting method finishes.
Is there a best way of accomplishing this?
I could take all inputs and put them in one giant form.. but I hate that approach.
I've tried setTimeout for a brief second. This seems to work at times, but it feels so hacky. I delay the submit method from finishing.. allowing the emit to finish.. that just doesn't feel sustainable or right.
Is there a clear way of doing this? Thank you so much for the assistance.
<1-- Parent -->
<template>
<!-- CHILD -->
<LabExposureType v-if="lab"
#passLabExposureToParent="exposureOnSubmit">
</LabExposureType>
<div class="submitAndClear d-flex justify-center pb-3">
<v-btn color="success" class="mr-4" #click="submit">submit</v-btn>
</div>
</template>
data(){
exposureVals:{},
}
//Removed some data and others for brevity
methods:{
submit() {
//collect vals before doing this
//Exposure values
console.log('emitted exposure vals', this.exposureVals); <- this of course is empty has the below has not finished
},
//Emitted method
exposureOnSubmit(input) {
this.exposureVals = input
}
}
EDIT - Added code for more clarity
Parent -
<LabExposureType v-if="lab" :labState="exposureState" v-model="standardNum"
#passLabExposureToParent="exposureOnSubmit">
</LabExposureType>
CHILD -
<v-text-field v-if="this.isStandardMethod" v-model="standardNum" label="Organization and Standard Number"
class="text-caption primary--text" required :error-messages="standardNumErrors"
:value="modelValue" #input="$emit('update:modelValue', $event.target.value)"
#blur="$v.standardNum.$touch()"></v-text-field>
props and emits -
props: [ "labState", "modelValue"],
emits:['update:modelValue'],
Your child components should emit their values before the submit is ever clicked. Best practice is to use the v-model directive so that the parent always has the latest value of the child. Define the v-model name on the parent with whatever name you want, just make sure the prop name in the child component is named modelValue and that the value is emitted using event update:modelValue:
<!-- Parent -->
<child v-model="searchText" />
<!-- Child -->
<script>
export default {
props: ['modelValue'],
emits: ['update:modelValue']
}
</script>
<template>
<input
:value="modelValue"
#input="$emit('update:modelValue', $event.target.value)"
/>
</template>
when I need to pass some information between child and parent element I use props. But is there a way to pass elements to the component, for example like this
<MyComponent>
<router-link to="/oneOfTheList">OneOfTheList</router-link>
</MyComponent>
Router-Link seems to do it somehow...
How can I specify where the elements will be placed in my component
This is called slot
ComponentA.vue
<div>
<slot></slot>
</div>
ComponentB.vue
<component-a>
<span>test</span> // this part will be shown inside component A's slot tags
</component-a>
Here you go
How do I use the same global component in a parent view and child (to the parent) in VueJs?
At the moment the global component is getting triggered twice when I trigger a function in the child component.
Parent
<ChildCompt ref="childCompt" />
<Modal ref="modalA" />
<div #click="triggerModalParent()">
Trigger Modal
</div>
Trigger function triggerModalParent: this.$refs.modalA.show();
Child
<Modal ref="modalB" />
<div #click="triggerModalChild()">
Trigger Modal
</div>
Trigger function triggerModalChild: this.$refs.modalB.show();
Try using different refs for parent and child modal imports, at the moment your imports have the same ref, hence they both get triggered
I have this:
Login.vue has child FormGroup.vue
FormGroup.vue has two children - Input.vue and Label.vue
I have data() in Login.vue and how to v-model data from Input.vue that's inside FormGroup.vue?
You need to use template refs to access data/methods of child component. For example in Login you can access FormGroup by adding a ref attribute and accessing it as:
<form-group ref="FormGroup" />
this.$refs.FormGroup
And then going further down it can be
<label ref="Label" />
<input ref="Input" />
this.$refs.FormGroup.$refs.Input
this.$refs.FormGroup.$refs.Label
But be careful before using $refs the child component must be rendered or else it will be null. It happens when there is a condition v-if on child components or the element is waiting for an API to complete.
Check: https://v3.vuejs.org/guide/component-template-refs.html
I want to use transition,keep-alive,router-view at the same time in App.vue. And I want the router's component not be reused.
This is the doc in vue-router
One thing to note when using routes with params is that when the user navigates from /users/johnny to /users/jolyne, the same component instance will be reused.
in Vue2.x,I can use key to keep router's component not be reused.
<transition>
<keep-alive>
<router-view :key="$route.fullPath" ></router-view>
</keep-alive>
</transition>
But in Vue3.0 the code is like below.
<router-view v-slot="{ Component }">
<transition>
<keep-alive>
<component :is="Component" />
</keep-alive>
</transition>
</router-view>
Someone can help to keep router's component not be reused in Vue3.0? use key in router-view cant work.
The answer was provided as a comment by Michal Levý:
Place :key="$route.fullPath" on <component>