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..767486c0486b 100644 --- a/src/cdk/stepper/stepper-module.ts +++ b/src/cdk/stepper/stepper-module.ts @@ -9,7 +9,7 @@ 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'; @@ -23,6 +23,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], })