call parent method in child component using vue.js - vue.js

hello everyone i jusy wanna know how to call a perent function from a child component
i've tried to use the $parent to call the perent method but i have this error typeError: _this.$parent.forceRender is not a function
here's the parent method that i'm trying to call
methods: {
forceRender() {
this.componentKey += 1
}
},
and here's the child component as you can see i'm trying to call the parent method using the $parent
this.$parent.forceRender()

You can send the functions as a props to the child component jus like follows
<child-component :forceRender="forceRender" />
inside the child component you can received it like this
props: ['forceRender']
and then call it as
this.forceRender()

You should emit an event from child to parent component in order to run a parent method :
in child component:
this.$emit('force-render')
in parent component add #force-render to component tag with forceRender as handler :
<child-component #force-render="forceRender" />

Related

Call grandchild function from a child - vue.js

I have 4 components in vue, I want to call a grandchild function('refreshArtifact') from a child component, any idea how can I do it?
So here is my component hierarchy:
Parent : TeamManagment.vue
Children :TeamPlatform.vue & ManagementArtifcts.vue
GrandChild : TeamAction.vue (TeamPlatform.vue child)
i want to call the 'refreshArtifact' function in TeamAction.vue from the ManagmentArtifact.vue component.
In my opinion, you can't right now directly call a child function of a brother. So, with your code, you can't directly call a function of a component A, from a component B which is the brother of the A one.
But, you can do that with the grandparent component.
So, when the ManagmentArtifact.vue component need to call refreshArtifact function, you can emit an event. The TeamManagment.vue listen that event, and then pass use ref of TeamPlatform.vue component to call the function.
ManagmentArtifact.vue: this.$emit('callRefresh')
TeamManagment.vue: <ManagmentArtifact #callRefresh='refreshArtifact' />
<TeamPlatform ref='team' />
methods: { refreshArtifact(){ this.$ref.team.refreshArtifact() } }
You can read the doc here.

Get v-if expression/data as plain text in child component

Hy there,
I try to create a custom Vue component which is shown based on v-if directive. I also want to change the directive data (modalStatus) value from inside the component.
<modal v-if="modalStatus"></modal>
To update the data from the component i use a method similar to this.
closeModal () {
this.$parent.modalStatus = false
}
The problem is that sometimes i don't know the name of the data model (modalStatus) , can be anything.
My question is how can i get the data/expression name as a plain text from the modal component ?
I'm planing to use something like this to update the modalStatus
this.$parent['anyName'] = false
Thanks and stay safe !
Later Edit. I know how to accomplish all of the above using props or v-model. I wonder if is possible using strictly v-if. Thanks!
There are several approaches to get to a method or property in the parent component from the child.
The 'Vue Way' is to emit a message telling the parent to close.
Send the name in as a property
Parent
<child modalName='modalStatus' />
Child
this.$parent[this.modalName]=false
Send in a method
Parent
<child :close='onClose' />
// component method
onClose(){
this.modalStatus=false
}
Child
this.close()
Emit a message
Parent
<child-component #close='modalStatus=false' />
// or call a method
<child-component #close='onClose' />
// component method
onClose(){
this.modalStatus=false
}
Child
this.$emit('close')

Vue lifecycle hook - conditionally prevent creation

Is there a way to prevent component creation during the lifecycle hook? For example:
beforeCreated() {
//checking value from vuex store
if (this.$store.state.attendeesCount >= this.$store.state.maxAttendees) {
//prevent further propagation, don't create an instance of component
}
}
The case is, I have a parent component with multiple child components which contain form for creating attendees (1 component = 1 attendee). I would like to prevent the creation of the child component if the seminar is already fully booked.
Update:
Parent component is base component for dozen of multirow form components and I didn't want to perform checks there to keep it as abstract as possible.
Instead of actually preventing creation of child component during the lifecycle hook, I have emitted custom event once the condition is met. Parent component listens to this custom event, and deletes child component instance.
Child:
beforeCreate() {
if (this.$store.state.attendeesCount >=
this.$store.state.maxAttendees) {
this.$emit('preventCreation', {message: 'No more places'})
}
}
Parent:
<template>
<component v-for="(item, index) in components"
#preventCreation="preventCreation(index, $event)"
...
>
</component>
...
</template>
...
methods(){
preventCreation(index, payload){
this.components.splice(index, 1)
alert(payload.msg)
}
}

ngOnInit or ngOnChanges not called while manually calling changeDetect() on a component

I have 3 component out of which p1 is parent and c1 and c2 is child ,
in c2 i am triggering the change detection by calling
this.changeDetecionRef.detectChanges()
But this will not triggered . no ngOnChanges or ngOnInit function get called of Parent and child component.
Does I have to update any property i.e binding data from parent to child or child to parent .
ngOnChanges is called only when the data-bound property was changed.
ngOnInit() is called, After all of the injected dependencies resolved. (It should call after ngOnChanges())
binding data from parent to child component,
parent.component.ts
#Component({
selector:'parent-component',
template:`
<h1>Welcome</h1>
<button (click)="changeCount()">Change</button>
<child-component [count]=Counter></child-component>`,
})
export class ParentComponent{
Counter=2;
changeCount(){
this.Counter++;
}
}
child.component.ts
#Component({
selector:'child-component',
template:`<h2>Total Count {{count}}</h2>`
})
export class ChildComponent{
#Input() count:number;
}
detectchanges() method should be called after updating the property,
for example,
export class ParentComponent{
Counter=2;
changeCount(){
this.Counter++;
this.changeDetecionRef.detectChanges();
}
}

Notify parent component as soon as event occurs in child event?

I need that when a user clicks a button on the child component the parent component receives cart.lenght to be assigned the count property of an element.
Child component code
<q-btn flat round color="faded" icon="fas fa-shopping-cart" #click="cart(item.id)"/>
cart: function (Id) {
let cart = []
cart.push(Id)
this.$emit('totalItensCart')
this.$q.localStorage.set('cart', cart)
}
How do I display the cart.length value in the count property that is in the parent component?
Parent component code
<q-route-tab
count="5"
icon="fas fa-cart-plus"
to="/cart"
exact
slot="title"/>
As per the vue event documentation, we want to emit an event from the child component to the parent component. You are correct with the this.$emit method, but it can take two parameters in order to pass data, like so:
this.$emit("name", data);
So, let's emit a count of the number of items in the cart from the first child:
this.$emit("cartUpdate", cart.length);
Now we need to handle this in the parent. We'll first need a data property to keep track of the totalCartItems in the parent:
data: function () {
return {
totalCartItems: null
}
}
Assuming that both of your code snippets are in different children of the same parent, and that the first child (the one that emits cartUpdate) has the component name first-child:
<first-child #cartUpdate="cartUpdate"></first-child>
This will call the cartUpdate() method in the parent component whenever the child emits an event called cartUpdate (using the # shorthand for v-on). The method is very simple, only updating the totalCartItems data property in the parent:
cartUpdate: function (totalCartItems) {
this.totalCartItems = totalCartItems;
}
Finally, let's ensure this gets updated in the second child component by binding it to the data value:
<q-route-tab
:count="totalCartItems"
icon="fas fa-cart-plus"
to="/cart"
exact
slot="title"/>