Skip to content

Commit

Permalink
Add a new resetWizard directive (#48)
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
madoar authored Sep 27, 2017
1 parent c1df020 commit b1dc46a
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 10 deletions.
28 changes: 24 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ To use this wizard component in an angular project simply add a `wizard` compone
</wizard>
```

## Components

### \<wizard\>
The `<wizard>` environment is the environment, in which you define the steps belonging to your wizard.
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.
Expand Down Expand Up @@ -227,6 +229,8 @@ Possible `<wizard-completion-step>` parameters:
| [canEnter] | `function(MovingDirection): boolean` \| `function(MovingDirection): Promise<boolean>` \| `boolean` | true |
| (stepEnter) | `function(MovingDirection): void` | null |

## Directives

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

#### Parameter overview
Possible `[enableBackLinks]` parameters:
Possible `enableBackLinks` parameters:

| Parameter name | Possible Values | Default Value |
| ----------------------------- | ---------------------------------------------------------------------------------------------------- | ------------- |
Expand Down Expand Up @@ -372,7 +376,7 @@ Possible parameters:

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

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

#### Parameter overview
Possible `[wizardStep]` parameters:
Possible `wizardStep` parameters:

| Parameter name | Possible Values | Default Value |
| ----------------------------- | ---------------------------------------------------------------------------------------------------- | ------------- |
Expand Down Expand Up @@ -416,7 +420,7 @@ that contains the wizard completion step.
```

#### Parameter overview
Possible `[wizardCompletionStep]` parameters:
Possible `wizardCompletionStep` parameters:

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

### \[resetWizard\]
Sometimes it's also required to reset the wizard to its initial state.
In such a case you can use the `resetWizard` directive.
This directive can be added to a button or a link for example.
When clicking on this element, the wizard will automatically reset to its `defaultStepIndex`.

In addition it's possible to define an `EventEmitter`, that is called when the wizard is being reset.
This `EventEmitter` can be bound to the `(finalize)` input of the `resetWizard` directive.

#### Parameter overview
Possible `resetWizard` parameters:

| Parameter name | Possible Values | Default Value |
| ----------------------------- | ---------------------------------------------------------------------------------------------------- | ------------- |
| (finalize) | `function(): void` | null |

### Accessing the wizard component instance
Sometimes it's required to access the wizard component directly.
In such a case you can get the instance of the used wizard component in your own component via:
Expand Down
13 changes: 9 additions & 4 deletions src/directives/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
/**
* Created by marc on 29.12.16.
*/

export {EnableBackLinksDirective} from './enable-back-links.directive';
export {GoToStepDirective} from './go-to-step.directive';
export {NextStepDirective} from './next-step.directive';
export {PreviousStepDirective} from './previous-step.directive';
export {OptionalStepDirective} from './optional-step.directive';
export {WizardStepTitleDirective} from './wizard-step-title.directive';
export {EnableBackLinksDirective} from './enable-back-links.directive';
export {PreviousStepDirective} from './previous-step.directive';
export {ResetWizardDirective} from './reset-wizard.directive';
export {SelectedStepDirective} from './selected-step.directive';
export {WizardCompletionStepDirective} from './wizard-completion-step.directive';
export {WizardStepDirective} from './wizard-step.directive';
export {WizardStepTitleDirective} from './wizard-step-title.directive';




136 changes: 136 additions & 0 deletions src/directives/reset-wizard.directive.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import {OptionalStepDirective} from './optional-step.directive';
import {Component} from '@angular/core';
import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {WizardModule} from '../wizard.module';
import {WizardState} from '../navigation/wizard-state.model';
import {NavigationMode} from '../navigation/navigation-mode.interface';
import {ResetWizardDirective} from './reset-wizard.directive';

@Component({
selector: 'test-wizard',
template: `
<wizard>
<wizard-step stepTitle='Steptitle 1'>
Step 1
</wizard-step>
<wizard-step stepTitle='Steptitle 2'>
Step 2
<button type="button" resetWizard>Reset (normal)</button>
<button type="button" resetWizard (finalize)='cleanup()'>Reset (cleanup)</button>
<button type="button" reset (finalize)='cleanup()'>Reset (cleanup short)</button>
</wizard-step>
</wizard>
`
})
class WizardTestComponent {
public eventLog: Array<string> = [];

public cleanup(): void {
this.eventLog.push('Cleanup done!');
};
}

describe('ResetWizardDirective', () => {
let wizardTest: WizardTestComponent;
let wizardTestFixture: ComponentFixture<WizardTestComponent>;

let wizardState: WizardState;
let navigationMode: NavigationMode;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [WizardTestComponent],
imports: [WizardModule]
}).compileComponents();
}));

beforeEach(() => {
wizardTestFixture = TestBed.createComponent(WizardTestComponent);
wizardTestFixture.detectChanges();

wizardTest = wizardTestFixture.componentInstance;
wizardState = wizardTestFixture.debugElement.query(By.css('wizard')).injector.get(WizardState);
navigationMode = wizardState.navigationMode;
});

it('should create an instance', () => {
expect(wizardTestFixture.debugElement.query(By.directive(ResetWizardDirective))).toBeTruthy();
expect(wizardTestFixture.debugElement.queryAll(By.directive(ResetWizardDirective)).length).toBe(3);
});

it('should reset the wizard correctly 1', fakeAsync(() => {
let resetButtons = wizardTestFixture.debugElement
.queryAll(By.directive(ResetWizardDirective));

navigationMode.goToStep(1);
tick();
wizardTestFixture.detectChanges();

expect(wizardState.getStepAtIndex(0).selected).toBe(false);
expect(wizardState.getStepAtIndex(0).completed).toBe(true);
expect(wizardState.getStepAtIndex(1).selected).toBe(true);
expect(wizardState.getStepAtIndex(1).completed).toBe(false);
expect(wizardTest.eventLog).toEqual([]);

resetButtons[0].nativeElement.click();
tick();
wizardTestFixture.detectChanges();

expect(wizardState.getStepAtIndex(0).selected).toBe(true);
expect(wizardState.getStepAtIndex(0).completed).toBe(false);
expect(wizardState.getStepAtIndex(1).selected).toBe(false);
expect(wizardState.getStepAtIndex(1).completed).toBe(false);
expect(wizardTest.eventLog).toEqual([]);
}));

it('should reset the wizard correctly 2', fakeAsync(() => {
let resetButtons = wizardTestFixture.debugElement
.queryAll(By.directive(ResetWizardDirective));

navigationMode.goToStep(1);
tick();
wizardTestFixture.detectChanges();

expect(wizardState.getStepAtIndex(0).selected).toBe(false);
expect(wizardState.getStepAtIndex(0).completed).toBe(true);
expect(wizardState.getStepAtIndex(1).selected).toBe(true);
expect(wizardState.getStepAtIndex(1).completed).toBe(false);
expect(wizardTest.eventLog).toEqual([]);

resetButtons[1].nativeElement.click();
tick();
wizardTestFixture.detectChanges();

expect(wizardState.getStepAtIndex(0).selected).toBe(true);
expect(wizardState.getStepAtIndex(0).completed).toBe(false);
expect(wizardState.getStepAtIndex(1).selected).toBe(false);
expect(wizardState.getStepAtIndex(1).completed).toBe(false);
expect(wizardTest.eventLog).toEqual(['Cleanup done!']);
}));

it('should reset the wizard correctly 3', fakeAsync(() => {
let resetButtons = wizardTestFixture.debugElement
.queryAll(By.directive(ResetWizardDirective));

navigationMode.goToStep(1);
tick();
wizardTestFixture.detectChanges();

expect(wizardState.getStepAtIndex(0).selected).toBe(false);
expect(wizardState.getStepAtIndex(0).completed).toBe(true);
expect(wizardState.getStepAtIndex(1).selected).toBe(true);
expect(wizardState.getStepAtIndex(1).completed).toBe(false);
expect(wizardTest.eventLog).toEqual([]);

resetButtons[2].nativeElement.click();
tick();
wizardTestFixture.detectChanges();

expect(wizardState.getStepAtIndex(0).selected).toBe(true);
expect(wizardState.getStepAtIndex(0).completed).toBe(false);
expect(wizardState.getStepAtIndex(1).selected).toBe(false);
expect(wizardState.getStepAtIndex(1).completed).toBe(false);
expect(wizardTest.eventLog).toEqual(['Cleanup done!']);
}));
});
52 changes: 52 additions & 0 deletions src/directives/reset-wizard.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {Directive, EventEmitter, HostListener, Output} from '@angular/core';
import {WizardState} from '../navigation/wizard-state.model';
import {NavigationMode} from '../navigation/navigation-mode.interface';

/**
* The `resetWizard` directive can be used to reset the wizard to its initial state.
* This directive accepts an output, which can be used to specify some custom cleanup work during the reset process.
*
* ### Syntax
*
* ```html
* <button resetWizard (finalize)="custom reset task">...</button>
* ```
*
* @author Marc Arndt
*/
@Directive({
selector: '[reset], [resetWizard]'
})
export class ResetWizardDirective {
/**
* An [[EventEmitter]] containing some tasks to be done, directly before the wizard is being reset
*/
@Output()
public finalize: EventEmitter<void> = new EventEmitter();

/**
* The navigation mode
*
* @returns {NavigationMode}
*/
private get navigationMode(): NavigationMode {
return this.wizardState.navigationMode;
}

/**
* Constructor
*
* @param wizardState The wizard state
*/
constructor(private wizardState: WizardState) { }

/**
* Resets the wizard
*/
@HostListener('click', ['$event']) onClick(): void {
// do some optional cleanup work
this.finalize.emit();
// reset the wizard to its initial state
this.navigationMode.reset();
}
}
File renamed without changes.
7 changes: 5 additions & 2 deletions src/wizard.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {EnableBackLinksDirective} from './directives/enable-back-links.directive
import {WizardStepDirective} from './directives/wizard-step.directive';
import {WizardCompletionStepDirective} from './directives/wizard-completion-step.directive';
import {SelectedStepDirective} from './directives/selected-step.directive';
import {ResetWizardDirective} from './directives/reset-wizard.directive';

/**
* The module defining all the content inside `ng2-archwizard`
Expand All @@ -35,7 +36,8 @@ import {SelectedStepDirective} from './directives/selected-step.directive';
EnableBackLinksDirective,
WizardStepDirective,
WizardCompletionStepDirective,
SelectedStepDirective
SelectedStepDirective,
ResetWizardDirective
],
imports: [
CommonModule
Expand All @@ -53,7 +55,8 @@ import {SelectedStepDirective} from './directives/selected-step.directive';
EnableBackLinksDirective,
WizardStepDirective,
WizardCompletionStepDirective,
SelectedStepDirective
SelectedStepDirective,
ResetWizardDirective
]
})
export class WizardModule {
Expand Down

0 comments on commit b1dc46a

Please sign in to comment.