diff --git a/src/lib/stepper/step-header.html b/src/lib/stepper/step-header.html
index fac0b329b18c..2d35efdba267 100644
--- a/src/lib/stepper/step-header.html
+++ b/src/lib/stepper/step-header.html
@@ -3,15 +3,27 @@
[class.mat-step-icon-not-touched]="state == 'number' && !selected"
[ngSwitch]="state">
- {{index + 1}}
+
+
+ {{index + 1}}
+
-
+
create
-
+
done
diff --git a/src/lib/stepper/step-header.ts b/src/lib/stepper/step-header.ts
index 13157c34e7a7..66adfff9f0a5 100644
--- a/src/lib/stepper/step-header.ts
+++ b/src/lib/stepper/step-header.ts
@@ -20,6 +20,7 @@ import {
import {Subscription} from 'rxjs/Subscription';
import {MatStepLabel} from './step-label';
import {MatStepperIntl} from './stepper-intl';
+import {MatStepperIconContext} from './stepper-icon';
@Component({
@@ -44,7 +45,7 @@ export class MatStepHeader implements OnDestroy {
@Input() label: MatStepLabel | string;
/** Overrides for the header icons, passed in via the stepper. */
- @Input() iconOverrides: {[key: string]: TemplateRef};
+ @Input() iconOverrides: {[key: string]: TemplateRef};
/** Index of the given step. */
@Input() index: number;
@@ -87,6 +88,15 @@ export class MatStepHeader implements OnDestroy {
return this._element.nativeElement;
}
+ /** Template context variables that are exposed to the `matStepperIcon` instances. */
+ _getIconContext(): MatStepperIconContext {
+ return {
+ index: this.index,
+ active: this.active,
+ optional: this.optional
+ };
+ }
+
focus() {
this._getHostElement().focus();
}
diff --git a/src/lib/stepper/stepper-icon.ts b/src/lib/stepper/stepper-icon.ts
index b2bf79fe14d1..c8cc8556072e 100644
--- a/src/lib/stepper/stepper-icon.ts
+++ b/src/lib/stepper/stepper-icon.ts
@@ -8,6 +8,16 @@
import {Directive, Input, TemplateRef} from '@angular/core';
+/** Template context available to an attached `matStepperIcon`. */
+export interface MatStepperIconContext {
+ /** Index of the step. */
+ index: number;
+ /** Whether the step is currently active. */
+ active: boolean;
+ /** Whether the step is optional. */
+ optional: boolean;
+}
+
/**
* Template to be used to override the icons inside the step header.
*/
@@ -16,7 +26,7 @@ import {Directive, Input, TemplateRef} from '@angular/core';
})
export class MatStepperIcon {
/** Name of the icon to be overridden. */
- @Input('matStepperIcon') name: 'edit' | 'done';
+ @Input('matStepperIcon') name: 'edit' | 'done' | 'number';
- constructor(public templateRef: TemplateRef) { }
+ constructor(public templateRef: TemplateRef) {}
}
diff --git a/src/lib/stepper/stepper.md b/src/lib/stepper/stepper.md
index 37ac9a30d3b4..d8fafef1eef3 100644
--- a/src/lib/stepper/stepper.md
+++ b/src/lib/stepper/stepper.md
@@ -124,7 +124,8 @@ this default `completed` behavior by setting the `completed` attribute as needed
#### Overriding icons
By default, the step headers will use the `create` and `done` icons from the Material design icon
set via `` elements. If you want to provide a different set of icons, you can do so
-by placing a `matStepperIcon` for each of the icons that you want to override:
+by placing a `matStepperIcon` for each of the icons that you want to override. The `index`,
+`active`, and `optional` values of the individual steps are available through template variables:
```html
@@ -136,6 +137,11 @@ by placing a `matStepperIcon` for each of the icons that you want to override:
done_all
+
+
+ {{index + 10}}
+
+
```
diff --git a/src/lib/stepper/stepper.spec.ts b/src/lib/stepper/stepper.spec.ts
index e3198496c70c..57c964336512 100644
--- a/src/lib/stepper/stepper.spec.ts
+++ b/src/lib/stepper/stepper.spec.ts
@@ -354,6 +354,13 @@ describe('MatStepper', () => {
expect(header.textContent).toContain('Custom done');
});
+
+ it('should allow for the `number` icon to be overridden with context', () => {
+ const stepperDebugElement = fixture.debugElement.query(By.directive(MatStepper));
+ const headers = stepperDebugElement.nativeElement.querySelectorAll('mat-step-header');
+
+ expect(headers[2].textContent).toContain('III');
+ });
});
describe('RTL', () => {
@@ -1025,6 +1032,9 @@ class SimpleStepperWithStepControlAndCompletedBinding {
Custom edit
Custom done
+
+ {{getRomanNumeral(index + 1)}}
+
Content 1
Content 2
@@ -1032,7 +1042,21 @@ class SimpleStepperWithStepControlAndCompletedBinding {
`
})
-class IconOverridesStepper {}
+class IconOverridesStepper {
+ getRomanNumeral(value: number) {
+ return {
+ 1: 'I',
+ 2: 'II',
+ 3: 'III',
+ 4: 'IV',
+ 5: 'V',
+ 6: 'VI',
+ 7: 'VII',
+ 8: 'VIII',
+ 9: 'IX'
+ }[value];
+ }
+}
@Component({
template: `
diff --git a/src/lib/stepper/stepper.ts b/src/lib/stepper/stepper.ts
index 3efd2f86121d..b51f2c78b1dc 100644
--- a/src/lib/stepper/stepper.ts
+++ b/src/lib/stepper/stepper.ts
@@ -31,7 +31,7 @@ import {takeUntil} from 'rxjs/operators/takeUntil';
import {MatStepHeader} from './step-header';
import {MatStepLabel} from './step-label';
import {matStepperAnimations} from './stepper-animations';
-import {MatStepperIcon} from './stepper-icon';
+import {MatStepperIcon, MatStepperIconContext} from './stepper-icon';
/** Workaround for https://github.com/angular/angular/issues/17849 */
export const _MatStep = CdkStep;
@@ -83,20 +83,18 @@ export class MatStepper extends CdkStepper implements AfterContentInit {
@ContentChildren(MatStepperIcon) _icons: QueryList;
/** Consumer-specified template-refs to be used to override the header icons. */
- _iconOverrides: {[key: string]: TemplateRef} = {};
+ _iconOverrides: {[key: string]: TemplateRef} = {};
ngAfterContentInit() {
const icons = this._icons.toArray();
- const editOverride = icons.find(icon => icon.name === 'edit');
- const doneOverride = icons.find(icon => icon.name === 'done');
- if (editOverride) {
- this._iconOverrides.edit = editOverride.templateRef;
- }
+ ['edit', 'done', 'number'].forEach(name => {
+ const override = icons.find(icon => icon.name === name);
- if (doneOverride) {
- this._iconOverrides.done = doneOverride.templateRef;
- }
+ if (override) {
+ this._iconOverrides[name] = override.templateRef;
+ }
+ });
// Mark the component for change detection whenever the content children query changes
this._steps.changes.pipe(takeUntil(this._destroyed)).subscribe(() => this._stateChanged());