Vue lifecycle hook - conditionally prevent creation - vue.js

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)
}
}

Related

How to change props in child component created using v-for in VueJs 3

I have a parent component creating child components using v-for directive:
<div class="planlist">
<ul id="planOl">
<PlanLego
v-for="action in store.plan"
:v-if="action !== activeStep"
:action_id="action.act_id"
:actor="action.actor"
:blocked="action.blocked"
:key="action.act_id"
#choose="planClick"
#fix="changeActor"
/>
</ul>
</div>
and I'm emitting a signal from the child component:
this.$emit('fix', {
act_id: this.action_id,
actor: this.actor
});
My question is:
how can I access and change the properties (for example actor) of this specific child component that emitted the signal? thanks in advance.
As per my understanding, You want to update the actor for the specific child in the parent component based on the act_id passed from child. If Yes, You can achieve this by iterating the original array object in the parent.
In the parent component, Your changeActor method should be like this :
In template :
#fix="changeActor($event)"
In script :
changeActor(emittedObj) {
store.plan.forEach(item => {
if (item.act_id === emittedObj.act_id) {
item.actor = emittedObj.actor
}
});
}

call parent method in child component using 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" />

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"/>

How can I get a child component's watcher's updated value from parent component in Vue 2?

I have two components that are in a parent-child relationship. In the child select component I've defined a watcher for the currently selected value and I want the parent to get the updated value whenever it changes. I tried to use events but the parent can only listen to its own vm.
In the child component
watch: {
selected (value) {
this.$emit('selectedYearChange', value)
}
}
In the parent
mounted () {
this.$on('selectedYearChange', function (value) {
this.selectedYear = value
})
}
This obviously doesn't work because of the reason I mentioned above.
I wasn't able to find relevant examples in the documentation.
You can setup an event listener on the child component element itself where its used in the parent and pass it a method to be executed
//parent component
<div id="app>
<child-comp #selected-year-change='changeYear'></child-comp>
</div>
In your parent component use the method changeYear to change the value of `selectedYear'
methods:{
//you get the event as the parameter
changeYear(value){
this.selectedYear = value
}
}
See the fiddle
And avoid using camelCase for event names use kebab-case instead as HTML attributes are case-insensitive and may cause problems
html:
<Parent>
<Child #selected-year-change=HandleChange(data)></Child>
</Parent>
Javascript/Child Component:
watch: {
selected (value) {
this.$emit('selectedYearChange', value)
}
}
Javascript/Parent Component:
HandleChange: function(data){}
good luck. maybe work!