Preventing a global component getting triggered twice in vue - vue.js

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

Related

Have Parent Component Wait till Child has emitted data back to parent ? (Using Vue 2)

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>

Multiple buttons in the child component with the methods in the parent component

I have a component with two buttons, each with an unique function:
<template>
<v-container>
<v - button ref = "button" / >
<v - button ref = "buttons" / >
</v-container>
</template>
How I want to address both buttons in the parent and apply my two functions, I have written in the parent, on them.
<Button #click="refer to the two buttons" />
...
<script>
methodOne(){
console.log("A")
}
methodTwo() {
console.log("B")
}
</script>
I just don't know how do that correctly. Short: having multiple buttons in the child component and multiple functions in the parent component who should be triggered when the buttons in the child component are triggered.
you can use Vue $emit function inside a child component. So:
Your child component
<template>
<div>
<button #click="$emit('aButttonClick')">Button A</button>
<button #click="$emit('bButttonClick')">Button B</button>
</div>
</template>
your parent component
<ButtonComponent #aButttonClick="methodOne" #bButttonClick="methodTwo" />
...
<script>
methodOne(){
console.log("A")
}
methodTwo() {
console.log("B")
}
</script>
And you can use emit function inside a function. And you can add additional params to.
See here https://v2.vuejs.org/v2/guide/components.html

Can I v-model input that is child of child (don't know how to ask)

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

Clicking non Vuetify button does not update data in v-data-table

In the code pen I have two buttons. One Vuetify and the other not. both should call the updateData() function but only the Vuetify component is able to run it succesfully. How can I call the method defined in the component from outside the app div?
https://codepen.io/entropy283/pen/rNxMXGX?editors=1010
You are trying to trigger updateData method, which is accessible only inside the HTML element that Vue is mounted on. I assume you are mounting Vue to the element with id="app".
You have to put the button inside the <div id="app">:
<div id="app">
<button #click="updateData()">Button</button>
...
Or, if you don't need to access any Vue properties, you can just create a function inside script and trigger it with onclick event. Keep in mind that #click is also not accessible outside of Vue:
<button onclick="updateData()">Button</button>
<div id="app">
...
<script>
function updateData() {
console.log('test')
}
</script>

Vue child component wait for props

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>