Skip to content

Instantly share code, notes, and snippets.

@nickjohnson-dev
Last active March 31, 2016 02:35
Show Gist options
  • Save nickjohnson-dev/45d1610b7f82ce565f8c5ac615df87b5 to your computer and use it in GitHub Desktop.
Save nickjohnson-dev/45d1610b7f82ce565f8c5ac615df87b5 to your computer and use it in GitHub Desktop.
Angular 2 Simple Wizard
import { Component } from 'angular2/core';
import { MyWizard } from './my-wizard';
import { MyWizardStep } from './my-wizard-step';
@Component({
selector: 'my-app',
directives: [
MyWizard,
MyWizardStep,
],
styles: [`
:host {
display: flex;
flex-direction: column;
flex-grow: 1;
}
my-wizard-step {
padding: 16px;
}
input[type=checkbox] {
margin-right: 8px;
}
`],
template: `
<my-wizard
[(activeStep)]="activeStep"
(finish)="onFinish()"
[isNextEnabled]="isNextEnabled()">
<my-wizard-step>
<label
for="check1">
<input
id="check1"
type="checkbox"
[(ngModel)]="firstChecked"
/>
Check Me First
</label>
</my-wizard-step>
<my-wizard-step>
<label
for="check2">
<input
id="check2"
type="checkbox"
[(ngModel)]="secondChecked"
/>
Check Me Second
</label>
</my-wizard-step>
</my-wizard>
`,
})
export class MyApp {
private firstChecked;
private secondChecked;
private activeStep = 1;
isNextEnabled() {
if (this.activeStep === 1) {
return !!this.firstChecked;
}
if (this.activeStep === 2) {
return !!this.secondChecked;
}
return true;
}
onFinish() {
console.log('Finished!');
}
}
import { Component } from 'angular2/core';
import { MyWizard } from './my-wizard';
@Component({
selector: 'my-wizard-step',
host: {
'[style.display]': 'isActive ? "flex" : "none"',
},
template: `
<ng-content></ng-content>
`,
})
export class MyWizardStep {
private isActive: boolean;
private step: number;
private setIsActive: (number) => void =
(step) => this.isActive = this.step === step;
private setStep: (number) => void =
(step) => this.step = step;
constructor(private parent:MyWizard) {}
ngOnInit() {
this.parent.incrementStepCount();
this.setStep(this.parent.getStepCount());
this.setIsActive(this.parent.getActiveStep());
this.parent.onActiveStepChange(this.setIsActive.bind(this));
}
}
import { Component, EventEmitter, Input, Output } from 'angular2/core';
@Component({
selector: 'my-wizard',
styles: [`
:host {
display: flex;
flex-direction: column;
flex-grow: 1;
}
.my-wizard__content {
flex-grow: 1;
}
.my-wizard__footer {
display: flex;
align-items: center;
justify-content: space-between;
flex-shrink: 0;
}
`],
template: `
<div
class="my-wizard__content">
<ng-content select="my-wizard-step"></ng-content>
</div>
<div
class="my-wizard__footer">
<button
[style.visibility]="activeStep === 1 ? 'hidden' : 'visible'"
(click)="activeStepChange.emit(activeStep - 1)">
Previous
</button>
{{activeStep}} / {{stepCount}}
<button
[attr.disabled]="isNextEnabled ? null : 'disabled'"
*ngIf="activeStep !== stepCount"
(click)="activeStepChange.emit(activeStep + 1)">
Next
</button>
<button
[attr.disabled]="isNextEnabled ? null : 'disabled'"
*ngIf="activeStep === stepCount"
(click)="finish.emit(activeStep + 1)">
{{finishText}}
</button>
</div>
`,
})
export class MyWizard {
@Input() finishText: string = 'Finish';
@Input() isNextEnabled: boolean = true;
@Input() activeStep: number = 1;
@Output() finish: EventEmitter<{}> = new EventEmitter();
@Output() activeStepChange: EventEmitter<number> = new EventEmitter();
private stepCount: number = 0;
public getActiveStep: () => number =
() => this.activeStep;
public onActiveStepChange: (callback:(step:number) => void) => void =
(callback: () => {}) => this.activeStepChange.subscribe(callback);
public getStepCount: () => number =
() => this.stepCount;
public incrementStepCount: () => void =
() => this.stepCount = this.stepCount + 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment