0

I have two components that I want them to interact with eachother. First is a modal that has a button in it that upon being clicked I want to go to the next step of my app. The second component is an angular material stepper. How can I make my app go to the next step upon clicking the button in the pop up modal?

I have been trying to do this using @ViewChild but am receiving this error in browser console when I click the button in my modal:

ERROR TypeError: Cannot read properties of undefined (reading 'next')
    at MyModalComponent.push../src/app/modals/my-modal/my-modal.component.ts.MyModalComponent.onLanguageSet

my-modal.component.ts:

import {Component, OnInit, Inject, ViewChild} from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';

@Component({
  selector: 'app-my-modal',
  templateUrl: './my-modal.component.html',
  styleUrls: ['./my-modal.component.scss']
})
export class MyModalComponent implements OnInit {
  
  constructor(
      public dialogRef: MatDialogRef<MyModalComponent>,
      @Inject(MAT_DIALOG_DATA) public data: any
  ) { }

  onLanguageSet() {
    this.dialogRef.close();
  }

  ngOnInit() {

  }

}

my-modal.component.html:

<div mat-dialog-actions fxLayoutAlign="end">
  <button mat-button mat-raised-button color="primary" (click)="onLanguageSet()">Begin configuration</button>
</div>

custom-stepper.component.ts:

import { ChangeDetectorRef, Component, Input, QueryList } from '@angular/core';
import { CdkStep, CdkStepper } from '@angular/cdk/stepper';

@Component({
  selector: 'app-custom-stepper',
  templateUrl: './custom-stepper.component.html',
  styleUrls: ['./custom-stepper.component.scss'],
    providers: [{provide: CdkStepper, useExisting: CustomStepperComponent}],
})

export class CustomStepperComponent extends CdkStepper {


    onClick(index: number): void {
      this.selectedIndex = index;
    }
}

custom-stepper.component.html:

  <footer>
    <mat-toolbar>
      <h2>Step {{selectedIndex + 1}}/{{_steps.length}}</h2>
      <span class="fill-space"></span>
      <button [ngClass]="selectedIndex > 0 ? 'noBtn': ''" mat-raised-button color="primary" class="naslednji-korak" [disabled]="(selectedIndex + 1)>_steps.length" cdkStepperNext>Begin configuration</button>
      <button [ngClass]="selectedIndex == 0 ? 'noBtn': ''" mat-raised-button color="secondary" class="naslednji-korak" [disabled]="selectedIndex == 0" cdkStepperPrevious>Previous step</button>
      <button [ngClass]="selectedIndex == 0 ? 'noBtn': ''" mat-raised-button color="primary" class="naslednji-korak" [disabled]="(selectedIndex + 1)==_steps.length" cdkStepperNext>Next step</button>
      <button [ngClass]="(selectedIndex + 1)<_steps.length ? 'noBtn': ''" mat-raised-button color="primary" class="naslednji-korak" [disabled]="(selectedIndex + 1)<_steps.length" (click)="reset()">Submit order</button>
    </mat-toolbar>
  </footer>

I am opening and closing the modal in configurator.component.ts with this code:

import { CustomStepperComponent } from '../custom-stepper/custom-stepper.component';        
@ViewChild('stepper') stepper: CustomStepperComponent;

    openDialog() {
            const dialogRef = this.dialog.open( MyModalComponent, {
                disableClose: true,
            });
    
            dialogRef.afterClosed().subscribe(result => {
                this.stepper.next();
                console.log('Zapri modal');
            });
        }
weinde
  • 1,074
  • 3
  • 13
  • 32
  • 1
    ViewChild only has access to the component where it's used. In your case, it only has access to element directly inside `my-modal.component.html`. It doesn't have access to the parent nor the childs of what's in your template. – Yannick Beauchamp-H Apr 20 '22 at 07:23
  • i cannot see any parent child relationship between two components, that's why viewchild decorator isn't working. try to call the click method using service – rahul tiwari Apr 20 '22 at 07:23
  • @rahultiwari how do I connect them with service? – weinde Apr 20 '22 at 07:30
  • @YannickBeauchamp-H is there a way you can provide some code expample? I don't know what you mean – weinde Apr 20 '22 at 07:31
  • I'd need to see where the stepper is used and where you open the modal to provide an example. But you could try using `afterClosed` where you open the dialog and advance to the next step this way instead of doing it inside the modal. – Yannick Beauchamp-H Apr 20 '22 at 07:37
  • @YannickBeauchamp-H I have added code at bottom of my post how I am opening and closing the modal – weinde Apr 20 '22 at 07:42
  • You already have `stepper.next()` in `afterClosed`. If you remove the stepper from `my-modal.component.ts`, it should be fine, otherwise you need to show how you declared `stepper` inside of `configurator.component.ts`. – Yannick Beauchamp-H Apr 20 '22 at 07:47
  • @YannickBeauchamp-H I have updated the bllow code how I am importing my custom stepper... I also removed the stepper from modal.component.ts – weinde Apr 20 '22 at 07:56
  • 1
    In `configurator.component.html`, you should have `#stepper` on your `` element. Without it, `ViewChild` is not going to work. Ex: `` – Yannick Beauchamp-H Apr 20 '22 at 08:02

1 Answers1

0

It seems like you're missing a template variable (in your case #stepper) in your my-modal.component.html.

And since you're using the next() method of that element, I assume the element will have to be of material stepper type! Otherwise, you'd see next is not a function error!

VahidM
  • 21
  • 4