From 641815efdb22be4413a14246c54c6c9aff80911b Mon Sep 17 00:00:00 2001 From: Najii1 Date: Wed, 22 Mar 2023 15:58:36 +0500 Subject: [PATCH] feat(material/stepper): implemented complete event on stepper. we currently don't have any output event that tells us if the stepper has completed or not, this change allow us to expose an event that will be called on matStepperComplete button directive. Fixes #12908 --- src/cdk/stepper/stepper-button.ts | 15 +++++++++++++++ src/cdk/stepper/stepper-module.ts | 13 +++++++++++-- src/cdk/stepper/stepper.ts | 14 ++++++++++++++ src/material/stepper/stepper-button.ts | 13 ++++++++++++- src/material/stepper/stepper-module.ts | 4 +++- 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/cdk/stepper/stepper-button.ts b/src/cdk/stepper/stepper-button.ts index 92f73c4e001c..e9d4b5218f8c 100644 --- a/src/cdk/stepper/stepper-button.ts +++ b/src/cdk/stepper/stepper-button.ts @@ -39,3 +39,18 @@ export class CdkStepperPrevious { constructor(public _stepper: CdkStepper) {} } + +/** Button that moves to the previous step in a stepper workflow. */ +@Directive({ + selector: 'button[cdkStepperComplete]', + host: { + '[type]': 'type', + '(click)': '_stepper.complete()', + }, +}) +export class CdkStepperComplete { + /** Type of the complete button. Defaults to "button" if not specified. */ + @Input() type: string = 'button'; + + constructor(public _stepper: CdkStepper) {} +} diff --git a/src/cdk/stepper/stepper-module.ts b/src/cdk/stepper/stepper-module.ts index 885df6fd4645..18a9110b8cb4 100644 --- a/src/cdk/stepper/stepper-module.ts +++ b/src/cdk/stepper/stepper-module.ts @@ -9,13 +9,21 @@ import {NgModule} from '@angular/core'; import {CdkStepper, CdkStep} from './stepper'; import {CdkStepLabel} from './step-label'; -import {CdkStepperNext, CdkStepperPrevious} from './stepper-button'; +import {CdkStepperNext, CdkStepperPrevious, CdkStepperComplete} from './stepper-button'; import {CdkStepHeader} from './step-header'; import {BidiModule} from '@angular/cdk/bidi'; @NgModule({ imports: [BidiModule], - exports: [CdkStep, CdkStepper, CdkStepHeader, CdkStepLabel, CdkStepperNext, CdkStepperPrevious], + exports: [ + CdkStep, + CdkStepper, + CdkStepHeader, + CdkStepLabel, + CdkStepperNext, + CdkStepperPrevious, + CdkStepperComplete, + ], declarations: [ CdkStep, CdkStepper, @@ -23,6 +31,7 @@ import {BidiModule} from '@angular/cdk/bidi'; CdkStepLabel, CdkStepperNext, CdkStepperPrevious, + CdkStepperComplete, ], }) export class CdkStepperModule {} diff --git a/src/cdk/stepper/stepper.ts b/src/cdk/stepper/stepper.ts index 8fec6f00156c..98d60b01d3af 100644 --- a/src/cdk/stepper/stepper.ts +++ b/src/cdk/stepper/stepper.ts @@ -339,6 +339,9 @@ export class CdkStepper implements AfterContentInit, AfterViewInit, OnDestroy { } private _orientation: StepperOrientation = 'horizontal'; + /** Event emitted when the stepper has been completed. */ + @Output() readonly stepperCompleted = new EventEmitter(); + constructor( @Optional() private _dir: Directionality, private _changeDetectorRef: ChangeDetectorRef, @@ -428,6 +431,17 @@ export class CdkStepper implements AfterContentInit, AfterViewInit, OnDestroy { this.selectedIndex = Math.max(this._selectedIndex - 1, 0); } + /** Triggers an Event that represents Stepper's 'matStepperComplete' button has been clicked. */ + complete(): void { + const stepsArray = this.steps.toArray(); + this.stepperCompleted.emit({ + selectedIndex: this.selectedIndex, + previouslySelectedIndex: this._selectedIndex, + selectedStep: stepsArray[this.selectedIndex], + previouslySelectedStep: stepsArray[this._selectedIndex], + }); + } + /** Resets the stepper to its initial state. Note that this includes clearing form data. */ reset(): void { this._updateSelectedItemIndex(0); diff --git a/src/material/stepper/stepper-button.ts b/src/material/stepper/stepper-button.ts index bb675b9579f2..4a0a92894803 100644 --- a/src/material/stepper/stepper-button.ts +++ b/src/material/stepper/stepper-button.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {CdkStepperNext, CdkStepperPrevious} from '@angular/cdk/stepper'; +import {CdkStepperNext, CdkStepperPrevious, CdkStepperComplete} from '@angular/cdk/stepper'; import {Directive} from '@angular/core'; /** Button that moves to the next step in a stepper workflow. */ @@ -30,3 +30,14 @@ export class MatStepperNext extends CdkStepperNext {} inputs: ['type'], }) export class MatStepperPrevious extends CdkStepperPrevious {} + +/** Button that triggers Output event what stepper have reached end of it is workflow. */ +@Directive({ + selector: 'button[matStepperComplete]', + host: { + 'class': 'mat-stepper-complete', + '[type]': 'type', + }, + inputs: ['type'], +}) +export class MatStepperComplete extends CdkStepperComplete {} diff --git a/src/material/stepper/stepper-module.ts b/src/material/stepper/stepper-module.ts index 86f1f348acc2..16e83062db90 100644 --- a/src/material/stepper/stepper-module.ts +++ b/src/material/stepper/stepper-module.ts @@ -15,7 +15,7 @@ import {MatIconModule} from '@angular/material/icon'; import {MatStepHeader} from './step-header'; import {MatStepLabel} from './step-label'; import {MatStep, MatStepper} from './stepper'; -import {MatStepperNext, MatStepperPrevious} from './stepper-button'; +import {MatStepperNext, MatStepperPrevious, MatStepperComplete} from './stepper-button'; import {MatStepperIcon} from './stepper-icon'; import {MAT_STEPPER_INTL_PROVIDER} from './stepper-intl'; import {MatStepContent} from './step-content'; @@ -39,6 +39,7 @@ import {MatStepContent} from './step-content'; MatStepHeader, MatStepperIcon, MatStepContent, + MatStepperComplete, ], declarations: [ MatStep, @@ -49,6 +50,7 @@ import {MatStepContent} from './step-content'; MatStepHeader, MatStepperIcon, MatStepContent, + MatStepperComplete, ], providers: [MAT_STEPPER_INTL_PROVIDER, ErrorStateMatcher], })