Reputation: 391
I have 3 components, a mat-horizontal-stepper, component A and component B. Both components are called into the stepper. I want to navigate from component A to component B under the requirement that condition C is met. Condition C is implemented in a method called pay() and called in a button. pay() is a method that makes a payment and if the payment is successful , it should navigate to step 2 otherwise if payment is unsuccessful, it should remain on step 1.
Issue : when condition C is met, that is, payment is successful. I am not able to navigate to step 2.
See my code below
Component A ts file
@ViewChild(MatStepper) stepper!: MatStepper;
pay() {
if(payment === "success"){
this.goToNextStep()
}
else{
console.warn("error")
}
goToNextStep() {
console.log('Going to the next step...');
if (this.stepper) {
this.stepper.next();
}
}
Component A html file
<button (click)="pay()">
go to step 2 when payment is successful
<button>
Component B html file
payment successful
Stepper html file
<mat-horizontal-stepper #stepper [linear]="true">
<mat-step>
<app-component-a></app-component-a>
</mat-step>
<mat-step>
<app-component-b></app-component-b>
</mat-step>
</mat-horizontal-stepper>
Upvotes: 0
Views: 1060
Reputation: 391
Solution 1 provided by @Zerotwelve
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-component-a',
template: `
<button (click)="pay()">Go to step 2 when payment is successful</button>
`
})
export class ComponentA {
@Output() paymentSuccess: EventEmitter<void> = new EventEmitter<void>();
pay() {
if (payment === 'success') {
this.paymentSuccess.emit();
} else {
console.warn('Payment error');
}
}
}
<mat-horizontal-stepper #stepper [linear]="true">
<mat-step>
<app-component-a (paymentSuccess)="goToNextStep()"></app-component-a>
</mat-step>
<mat-step>
<app-component-b></app-component-b>
</mat-step>
</mat-horizontal-stepper>
import { Component, ViewChild } from '@angular/core';
import { MatStepper } from '@angular/material/stepper';
@Component({
selector: 'app-stepper',
templateUrl: './stepper.component.html',
styleUrls: ['./stepper.component.css']
})
export class StepperComponent {
@ViewChild(MatStepper) stepper!: MatStepper;
goToNextStep() {
console.log('Going to the next step...');
if (this.stepper) {
this.stepper.next();
}
}
}
Solution 2 provided by @Zerotwelve
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-component-a',
template: `
<button (click)="pay()">Go to step 2 when payment is successful</button>
`
})
export class ComponentA {
@Input() stepper: MatStepper | undefined;
pay() {
if (payment === 'success' && this.stepper) {
this.stepper.next();
} else {
console.warn('Payment error');
}
}
}
<mat-horizontal-stepper #stepper [linear]="true">
<mat-step>
<app-component-a [stepper]="stepper"></app-component-a>
</mat-step>
<mat-step>
<app-component-b></app-component-b>
</mat-step>
</mat-horizontal-stepper>
Upvotes: 1
Reputation: 2361
Component A doesn't have access to the stepper in it's parent component.
this.stepper
will always be undefined
.
Component A should emit an event and then you can call this.stepper.next();
from it's parent or you can add an @Input
to Component A and pass the stepper as an input.
Upvotes: 1