Thanks for everyone who works on this project! I just upgraded to beta12 and am using the Stepper component now. I had a few proposals after using it for a bit. Please let me know what you think-I'd love to help contribute if we want any of these (:
Would like to add one more suggestion here as well:
5. Disabled step. Or a way to add/remove steps.
- Use Case: Additional steps depending on what is being selected in previous steps. (like a wizard form).
I was able to add steps with something like this:
<mat-step *ngFor="let invForm of inventoryForms"
[stepControl]="invForm.form" [label]="invForm.item.product.name">
</mat-step>
but if I go back to previous step, and change it so that these additional steps aren't required, and setting this.inventoryForms = []
, the steps are not removed from the stepper.
Even wrapping it inside a <ng-container *ngIf="inventoryForms.length > 0">
did not work. 馃槥
I got a work-around, but is probably a bad idea 馃槄
<mat-vertical-stepper #stepper></mat-vertical-stepper>
import { ViewChild } from '@angular/core';
import { MatVerticalStepper } from '@angular/material';
@ViewChild('stepper') stepper: MatVerticalStepper;
clearAdditionalForms(): void {
this.inventoryForms = [];
this.stepper._stateChanged(); // <- this : Marks the component to be change detected.
}
I would like to also leave a suggestion.
disabled attribute is must have.
For example: we have 5 steps, step N is disabled by business logic. Then it should be gray out and not editable
Perhaps related to 4. Animate Height: having it animate the same way tab transitions where you see the current content slide out
Have any one a solution for suggestion 1? I tried quickly the same as in https://github.com/angular/material2/issues/8014 but ran into same issues.
As @jdeanwaite suggested async step support is critical.
I need to create 5 step process, when user clicks Next I'd like to submit data from that step to server, so that user can come back later and resume process.
linear="true"
solves problem with disabling ability to move to next step before filling current, but there should be option to disable moving back. In my case when user submits current step by clicking Next
he can't move back. Currently he can click Back button or use labels to navigate, so disable attribute is a must have for me.
I'd like to add: it would be nice if we could implement the dynamicHeight
input that mat-tab-group has. I recently tried to replace a tab group with a stepper but I get painful layout problems due to each mat-step's height adapting to its content. Using a mat-tab-group I managed a workaround by setting dynamicHeight false. It seems the dynamicHeight behavior we have in mat-tab-group is something people are asking for anyway.
That is how to add steps dynamically -
<mat-step *ngIf="*expression*"></mat-step>
Anything new about disabling single steps?
EDIT
The way to disable steps is to add on the `
<mat-step [editable]="myStepEditable">...</mat-step>
It worked for me because I need to handle disabled after the step was
completed already...
I don't know if this can prevent entering next steps...
Another great limitation of the steppers is that you cannot grow it to fill the entire parent space. I have a horizontal stepper and I want that the steps content cover all the available space (vertically). AFAIK there is no way to obtain this basic functionality. Any suggestion?
@AGPX are you using @angular/flex-layout?
@tonysamperi for sure, the problem is that the step contents are put inside a div with the class 'mat-horizontal-stepper-content'. Unfortunately, if you add the style 'height: 100%' this will grow all the steps including the hidden (not actived step), because they are hidden through the style 'visibility:hidden' instead of 'display:none' and so the previous hidden steps shift down the actived one. In addition, I found no example of what I wish to achieve.
@AGPX can you do a stackblitz?
You can fork mine...
https://stackblitz.com/edit/angular-mat-stepper-program
@tonysamperi sorry, but the proxy of my company don't allow me to use stackblitz (I will make this example from my home, later). I try, however, to explain my problem now.
Looking at the generated DOM of the stepper you have:
<div class="mat-horizontal-content-container">
<div class="mat-horizontal-stepper-content ng-tns-c12-2 ng-trigger ng-trigger-stepTransition ng-star-inserted" role="tabpanel" id="cdk-step-content-0-0" aria-labelledby="cdk-step-label-0-0" aria-expanded="false" style="transform: translate3d(-100%, 0px, 0px); visibility: hidden;">
my contents of step 1 go here...
</div>
<div class="mat-horizontal-stepper-content ng-tns-c12-2 ng-trigger ng-trigger-stepTransition ng-star-inserted" role="tabpanel" id="cdk-step-content-0-0" aria-labelledby="cdk-step-label-0-0" aria-expanded="false" style="transform: translate3d(-100%, 0px, 0px); visibility: visible;">
my contents of step 2 go here...
</div>
</div>
The only way to expand my content vertically in order to cover the entire vertical space is to add the style 'height: 100%' to 'mat-horizontal-stepper-content' and 'mat-horizontal-content-container' classes. Unfortunately, the 'mat-horizontal-stepper-content' is shared amongs all the steps and this will grow also the step 1 div (that is hidden). The result is that the step 2 content is shifted down.
@tonysamperi to prevent entering next step you must use FormBuilder and FormControl, with attached validators. This validators sets property completed for step and you can not step forward until step is not completed. Try to use custom validators:
this.registrationFormGroup = this._formBuilder.group({
confirmPasswordControl: ['', Validators.required, passwordMatchValidator],
});
function passwordMatchValidator(g: FormGroup) {
return g.get('passwordControl').value === g.get('confirmPasswordControl').value ? null : {'mismatch': true}; }
Set registrationFormGroup to mat-step and form inside it
<mat-step [stepControl]="registrationFormGroup" label="Step 1">
<form class="registration" [formGroup]="registrationFormGroup">
and confirmPasswordControl to input in the step
<input type="password" matInput placeholder="Confirm password" formControlName="confirmPasswordControl" required>
also you can setup completed property manually in ts code
<mat-horizontal-stepper #stepper>
@ViewChild('stepper') stepper: MatStepper;
nextStep(): void {
this.stepper._steps.first.completed = true;
this.stepper.next();
}
@vanmxpx Yeah, you're right.
But I think it's not practical if you are in this case:
If I wanted to send form data to a rest endpoint, and wait for its response to allow navigation, I should add a dummy (like a required hidden) input to invalidate the whole form. I think there should be some better option to prevent navigation through the stepper-header.
@AGPX I asked you to prepare a Stackblitz because I want to see how directives on the non-compiled, apply to the compiled.
And then think to some hacky rule in the styles.css to overcome your issue (But still, if strictly necessary).
@tonysamperi if i understand you right, you can go like this:
setup steps not completed by default in html <mat-step label="袩芯写锌懈褋泻邪" [completed]="false">
and set step 'completed' after a server response. this.stepper.selected.completed = true;
. This not required any hacks with inputs.
Look throw stackblitz
@tonysamperi I have updated your sample in Stackblitz (from my home):
https://stackblitz.com/edit/angular-mat-stepper-program-8dkmen
Note that my example works if you try to replace the style 'visibility:hidden'
with 'display:none'
(for example from browser's DOM inspector) in all the divs with class 'mat-horizontal-stepper-content'
. I'm not sure why 'visibility'
was preferred over 'display'
, there is any drawback using it?
@vanmxpx thanks. Didn't know about the "complete" attr...
It could be even easier then...
HTML
<mat-step label="袩芯写锌懈褋泻邪" [completed]="completed">
<button (click)="completed()">COMPLETE</button>
</mat-step>
TS
completed = false;
complete(){
this.completed = true;
}
https://stackblitz.com/edit/mat-step-complete
@AGPX taking a look right now! I'm in CET 馃憤
@AGPX cos矛 pu貌 andarti bene?
https://stackblitz.com/edit/angular-mat-stepper-full-height?file=app/demo/demo.component.html
@tonysamperi eh... the div should cover the entire vertical space...
@AGPX sorry, it did when I posted...maybe I didn't save...
@AGPX ok it should work now...
https://stackblitz.com/edit/angular-mat-stepper-full-height
@tonysamperi thank you very much, it works! A bit tricky though, I think that this should be supported natively by the stepper component. Anyway, thanks again!
@tonysamperi @AGPX I had the same problem and found a pretty simple solution.
The Idea is, that the height: 100%
is only applied to the active step.
This can be achieved using following css-rule:
.mat-horizontal-stepper-content[aria-expanded=true] {
height: 100%;
display: flex;
flex-direction: column;
}
I used flex-direction: column
, so that the content of <mat-step>
can be laid out as a column, without adding an extra container.
I also added a css-class full-height
, which I configure in the style.css
. That way I can use ViewEncapsulation
.
So basically you only need to do the following:
<mat-horizontal-stepper>
has to be 100% high..mat-horizontal-content-container
has to be 100% high..mat-horizontal-stepper-content
of active step has to be 100% high (.mat-horizontal-stepper-content[aria-expanded=true]
)..mat-horizontal-stepper-content
of active step has to be 0px high (.mat-horizontal-stepper-content[aria-expanded=false]
).@Springrbua good to know. Thanks!
@Springrbua Thanks for the hint. However, IMHO, the stepper should support this capability natively. Generally speaking (coming from other frameworks), Angular Material should be by far more customizable.
@AGPX I agree, that the stepper should allow you to easily customize the height of th stepper-content.
Usually you want to have the buttons (back and next) always at the same spot and therefore you need a fixed height.
Angular Material should be by far more customizable.
I don't really agree with you on that. Angular Material follows the material design specs and does a great job at that. Of course, a few components could give a little more freedom, but not too much.
If you need more freedom, then you should probably use the CDK, which Angular Material uses under the hood.
Angular Material follows the material design specs...
@Springrbua probably my problem is actually material design, or better the decision to adopt it. My boss tell me "...remove the underline on the input text...", "...put label on the left...", "...change this and that..." and I found very very difficult to apply any cosmetic changes to Material. Probably Angular Material is not the framework tailored for our needs, but it's not my choice (probably it was chosen without a sufficient understanding of its philosophy)... so I have to found workarounds. Forgive me, I'm only a coder. Thanks anyway for the precious support!
@AGPX Take a look at the cdk, maybe it is what you are looking for. Basically all material components are build on top of it and add material design style to it. If you don't need material design style it might be what you are looking for.
@AGPX you should have a more "component-wise" approach.
Of course setting height for the stepper is a very specific change.
But if you want any inputs to have the label on the left, you just create a component which wraps a matInput but never sets the placeholder...Maybe this requires time, but it allows you to create a set based on your project (and always reusable even outside).
Angular Material should be by far more customizable.
Any plan to implement disabled
state or it's a no-go feature ?
This is very useful in order to have more dynamic steps without inserting/removing steps dynamically which would be not intuitive for the users.
Thanks a lot.
How can we set success after completion of all state?
@AGPX ok it should work now...
https://stackblitz.com/edit/angular-mat-stepper-full-height
I want the same. But want stepper fix at the bottom of the page & section should scroll.
Any idea how to achieve that.
@akvaliya if I remember correctly the stepper and the content are flex
.
You can swap the order with a simple rule: flex-direction: column-reverse
I'm trying to get the same style requested by @AGPX (horizontal stepper with the steps content cover all the available vertical space), but I'm struggling to get it. Even the workarounds suggested by @tonysamperi and @Springrbua aren't working for me, maybe they worked well when posted, but they don't for sure on version 10.1.3, that I'm using.
Any suggestion?
@kungufli I suggest not using github as stackoverflow.
I think you should create a post there and show what you've tried so far.
I think you should at least create a stackblitz with your environment so that anyone can take a look and maybe help you out!
Most helpful comment
disabled attribute is must have.
For example: we have 5 steps, step N is disabled by business logic. Then it should be gray out and not editable