Skip to content

Commit b1dc46a

Browse files
authored
Add a new resetWizard directive (#48)
- add a new resetWizard directive - fix the filename for the selectedStep directive tests - extend the README with some resetWizard directive specific details - add sections for Components and Directives to the README
1 parent c1df020 commit b1dc46a

File tree

6 files changed

+226
-10
lines changed

6 files changed

+226
-10
lines changed

README.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ To use this wizard component in an angular project simply add a `wizard` compone
6060
</wizard>
6161
```
6262

63+
## Components
64+
6365
### \<wizard\>
6466
The `<wizard>` environment is the environment, in which you define the steps belonging to your wizard.
6567
In addition to the contained wizard steps, `ng2-archwizard` enables you to define the location and the layout of the navigation bar inside your wizard.
@@ -227,6 +229,8 @@ Possible `<wizard-completion-step>` parameters:
227229
| [canEnter] | `function(MovingDirection): boolean` \| `function(MovingDirection): Promise<boolean>` \| `boolean` | true |
228230
| (stepEnter) | `function(MovingDirection): void` | null |
229231

232+
## Directives
233+
230234
### \[enableBackLinks\]
231235
In some cases it may be required that the user is allowed to leave an entered `wizard-completion-step`.
232236
In such a case you can enable this by adding the directive `[enableBackLinks]` to the `wizard-completion-step`.
@@ -238,7 +242,7 @@ In such a case you can enable this by adding the directive `[enableBackLinks]` t
238242
```
239243

240244
#### Parameter overview
241-
Possible `[enableBackLinks]` parameters:
245+
Possible `enableBackLinks` parameters:
242246

243247
| Parameter name | Possible Values | Default Value |
244248
| ----------------------------- | ---------------------------------------------------------------------------------------------------- | ------------- |
@@ -372,7 +376,7 @@ Possible parameters:
372376

373377
### \[wizardStep\]
374378
In some cases it may be a good idea to move a wizard step to a custom component.
375-
This can be done by defining adding the `[wizardStep]` directive to the component, that contains the wizard step.
379+
This can be done by defining adding the `wizardStep` directive to the component, that contains the wizard step.
376380

377381
```html
378382
<wizard>
@@ -387,7 +391,7 @@ This can be done by defining adding the `[wizardStep]` directive to the componen
387391
```
388392

389393
#### Parameter overview
390-
Possible `[wizardStep]` parameters:
394+
Possible `wizardStep` parameters:
391395

392396
| Parameter name | Possible Values | Default Value |
393397
| ----------------------------- | ---------------------------------------------------------------------------------------------------- | ------------- |
@@ -416,7 +420,7 @@ that contains the wizard completion step.
416420
```
417421

418422
#### Parameter overview
419-
Possible `[wizardCompletionStep]` parameters:
423+
Possible `wizardCompletionStep` parameters:
420424

421425
| Parameter name | Possible Values | Default Value |
422426
| ----------------------------- | ---------------------------------------------------------------------------------------------------- | ------------- |
@@ -426,6 +430,22 @@ Possible `[wizardCompletionStep]` parameters:
426430
| [canEnter] | `function(MovingDirection): boolean` \| `function(MovingDirection): Promise<boolean>` \| `boolean` | true |
427431
| (stepEnter) | `function(MovingDirection): void` | null |
428432

433+
### \[resetWizard\]
434+
Sometimes it's also required to reset the wizard to its initial state.
435+
In such a case you can use the `resetWizard` directive.
436+
This directive can be added to a button or a link for example.
437+
When clicking on this element, the wizard will automatically reset to its `defaultStepIndex`.
438+
439+
In addition it's possible to define an `EventEmitter`, that is called when the wizard is being reset.
440+
This `EventEmitter` can be bound to the `(finalize)` input of the `resetWizard` directive.
441+
442+
#### Parameter overview
443+
Possible `resetWizard` parameters:
444+
445+
| Parameter name | Possible Values | Default Value |
446+
| ----------------------------- | ---------------------------------------------------------------------------------------------------- | ------------- |
447+
| (finalize) | `function(): void` | null |
448+
429449
### Accessing the wizard component instance
430450
Sometimes it's required to access the wizard component directly.
431451
In such a case you can get the instance of the used wizard component in your own component via:

src/directives/index.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
/**
22
* Created by marc on 29.12.16.
33
*/
4-
4+
export {EnableBackLinksDirective} from './enable-back-links.directive';
55
export {GoToStepDirective} from './go-to-step.directive';
66
export {NextStepDirective} from './next-step.directive';
7-
export {PreviousStepDirective} from './previous-step.directive';
87
export {OptionalStepDirective} from './optional-step.directive';
9-
export {WizardStepTitleDirective} from './wizard-step-title.directive';
10-
export {EnableBackLinksDirective} from './enable-back-links.directive';
8+
export {PreviousStepDirective} from './previous-step.directive';
9+
export {ResetWizardDirective} from './reset-wizard.directive';
1110
export {SelectedStepDirective} from './selected-step.directive';
11+
export {WizardCompletionStepDirective} from './wizard-completion-step.directive';
12+
export {WizardStepDirective} from './wizard-step.directive';
13+
export {WizardStepTitleDirective} from './wizard-step-title.directive';
14+
15+
16+
1217

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import {OptionalStepDirective} from './optional-step.directive';
2+
import {Component} from '@angular/core';
3+
import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
4+
import {By} from '@angular/platform-browser';
5+
import {WizardModule} from '../wizard.module';
6+
import {WizardState} from '../navigation/wizard-state.model';
7+
import {NavigationMode} from '../navigation/navigation-mode.interface';
8+
import {ResetWizardDirective} from './reset-wizard.directive';
9+
10+
@Component({
11+
selector: 'test-wizard',
12+
template: `
13+
<wizard>
14+
<wizard-step stepTitle='Steptitle 1'>
15+
Step 1
16+
</wizard-step>
17+
<wizard-step stepTitle='Steptitle 2'>
18+
Step 2
19+
<button type="button" resetWizard>Reset (normal)</button>
20+
<button type="button" resetWizard (finalize)='cleanup()'>Reset (cleanup)</button>
21+
<button type="button" reset (finalize)='cleanup()'>Reset (cleanup short)</button>
22+
</wizard-step>
23+
</wizard>
24+
`
25+
})
26+
class WizardTestComponent {
27+
public eventLog: Array<string> = [];
28+
29+
public cleanup(): void {
30+
this.eventLog.push('Cleanup done!');
31+
};
32+
}
33+
34+
describe('ResetWizardDirective', () => {
35+
let wizardTest: WizardTestComponent;
36+
let wizardTestFixture: ComponentFixture<WizardTestComponent>;
37+
38+
let wizardState: WizardState;
39+
let navigationMode: NavigationMode;
40+
41+
beforeEach(async(() => {
42+
TestBed.configureTestingModule({
43+
declarations: [WizardTestComponent],
44+
imports: [WizardModule]
45+
}).compileComponents();
46+
}));
47+
48+
beforeEach(() => {
49+
wizardTestFixture = TestBed.createComponent(WizardTestComponent);
50+
wizardTestFixture.detectChanges();
51+
52+
wizardTest = wizardTestFixture.componentInstance;
53+
wizardState = wizardTestFixture.debugElement.query(By.css('wizard')).injector.get(WizardState);
54+
navigationMode = wizardState.navigationMode;
55+
});
56+
57+
it('should create an instance', () => {
58+
expect(wizardTestFixture.debugElement.query(By.directive(ResetWizardDirective))).toBeTruthy();
59+
expect(wizardTestFixture.debugElement.queryAll(By.directive(ResetWizardDirective)).length).toBe(3);
60+
});
61+
62+
it('should reset the wizard correctly 1', fakeAsync(() => {
63+
let resetButtons = wizardTestFixture.debugElement
64+
.queryAll(By.directive(ResetWizardDirective));
65+
66+
navigationMode.goToStep(1);
67+
tick();
68+
wizardTestFixture.detectChanges();
69+
70+
expect(wizardState.getStepAtIndex(0).selected).toBe(false);
71+
expect(wizardState.getStepAtIndex(0).completed).toBe(true);
72+
expect(wizardState.getStepAtIndex(1).selected).toBe(true);
73+
expect(wizardState.getStepAtIndex(1).completed).toBe(false);
74+
expect(wizardTest.eventLog).toEqual([]);
75+
76+
resetButtons[0].nativeElement.click();
77+
tick();
78+
wizardTestFixture.detectChanges();
79+
80+
expect(wizardState.getStepAtIndex(0).selected).toBe(true);
81+
expect(wizardState.getStepAtIndex(0).completed).toBe(false);
82+
expect(wizardState.getStepAtIndex(1).selected).toBe(false);
83+
expect(wizardState.getStepAtIndex(1).completed).toBe(false);
84+
expect(wizardTest.eventLog).toEqual([]);
85+
}));
86+
87+
it('should reset the wizard correctly 2', fakeAsync(() => {
88+
let resetButtons = wizardTestFixture.debugElement
89+
.queryAll(By.directive(ResetWizardDirective));
90+
91+
navigationMode.goToStep(1);
92+
tick();
93+
wizardTestFixture.detectChanges();
94+
95+
expect(wizardState.getStepAtIndex(0).selected).toBe(false);
96+
expect(wizardState.getStepAtIndex(0).completed).toBe(true);
97+
expect(wizardState.getStepAtIndex(1).selected).toBe(true);
98+
expect(wizardState.getStepAtIndex(1).completed).toBe(false);
99+
expect(wizardTest.eventLog).toEqual([]);
100+
101+
resetButtons[1].nativeElement.click();
102+
tick();
103+
wizardTestFixture.detectChanges();
104+
105+
expect(wizardState.getStepAtIndex(0).selected).toBe(true);
106+
expect(wizardState.getStepAtIndex(0).completed).toBe(false);
107+
expect(wizardState.getStepAtIndex(1).selected).toBe(false);
108+
expect(wizardState.getStepAtIndex(1).completed).toBe(false);
109+
expect(wizardTest.eventLog).toEqual(['Cleanup done!']);
110+
}));
111+
112+
it('should reset the wizard correctly 3', fakeAsync(() => {
113+
let resetButtons = wizardTestFixture.debugElement
114+
.queryAll(By.directive(ResetWizardDirective));
115+
116+
navigationMode.goToStep(1);
117+
tick();
118+
wizardTestFixture.detectChanges();
119+
120+
expect(wizardState.getStepAtIndex(0).selected).toBe(false);
121+
expect(wizardState.getStepAtIndex(0).completed).toBe(true);
122+
expect(wizardState.getStepAtIndex(1).selected).toBe(true);
123+
expect(wizardState.getStepAtIndex(1).completed).toBe(false);
124+
expect(wizardTest.eventLog).toEqual([]);
125+
126+
resetButtons[2].nativeElement.click();
127+
tick();
128+
wizardTestFixture.detectChanges();
129+
130+
expect(wizardState.getStepAtIndex(0).selected).toBe(true);
131+
expect(wizardState.getStepAtIndex(0).completed).toBe(false);
132+
expect(wizardState.getStepAtIndex(1).selected).toBe(false);
133+
expect(wizardState.getStepAtIndex(1).completed).toBe(false);
134+
expect(wizardTest.eventLog).toEqual(['Cleanup done!']);
135+
}));
136+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import {Directive, EventEmitter, HostListener, Output} from '@angular/core';
2+
import {WizardState} from '../navigation/wizard-state.model';
3+
import {NavigationMode} from '../navigation/navigation-mode.interface';
4+
5+
/**
6+
* The `resetWizard` directive can be used to reset the wizard to its initial state.
7+
* This directive accepts an output, which can be used to specify some custom cleanup work during the reset process.
8+
*
9+
* ### Syntax
10+
*
11+
* ```html
12+
* <button resetWizard (finalize)="custom reset task">...</button>
13+
* ```
14+
*
15+
* @author Marc Arndt
16+
*/
17+
@Directive({
18+
selector: '[reset], [resetWizard]'
19+
})
20+
export class ResetWizardDirective {
21+
/**
22+
* An [[EventEmitter]] containing some tasks to be done, directly before the wizard is being reset
23+
*/
24+
@Output()
25+
public finalize: EventEmitter<void> = new EventEmitter();
26+
27+
/**
28+
* The navigation mode
29+
*
30+
* @returns {NavigationMode}
31+
*/
32+
private get navigationMode(): NavigationMode {
33+
return this.wizardState.navigationMode;
34+
}
35+
36+
/**
37+
* Constructor
38+
*
39+
* @param wizardState The wizard state
40+
*/
41+
constructor(private wizardState: WizardState) { }
42+
43+
/**
44+
* Resets the wizard
45+
*/
46+
@HostListener('click', ['$event']) onClick(): void {
47+
// do some optional cleanup work
48+
this.finalize.emit();
49+
// reset the wizard to its initial state
50+
this.navigationMode.reset();
51+
}
52+
}

src/wizard.module.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {EnableBackLinksDirective} from './directives/enable-back-links.directive
1515
import {WizardStepDirective} from './directives/wizard-step.directive';
1616
import {WizardCompletionStepDirective} from './directives/wizard-completion-step.directive';
1717
import {SelectedStepDirective} from './directives/selected-step.directive';
18+
import {ResetWizardDirective} from './directives/reset-wizard.directive';
1819

1920
/**
2021
* The module defining all the content inside `ng2-archwizard`
@@ -35,7 +36,8 @@ import {SelectedStepDirective} from './directives/selected-step.directive';
3536
EnableBackLinksDirective,
3637
WizardStepDirective,
3738
WizardCompletionStepDirective,
38-
SelectedStepDirective
39+
SelectedStepDirective,
40+
ResetWizardDirective
3941
],
4042
imports: [
4143
CommonModule
@@ -53,7 +55,8 @@ import {SelectedStepDirective} from './directives/selected-step.directive';
5355
EnableBackLinksDirective,
5456
WizardStepDirective,
5557
WizardCompletionStepDirective,
56-
SelectedStepDirective
58+
SelectedStepDirective,
59+
ResetWizardDirective
5760
]
5861
})
5962
export class WizardModule {

0 commit comments

Comments
 (0)