Last active
December 4, 2016 19:14
-
-
Save ScottWhittaker/c4b5282d6f43a7254d0a2eba9c1fa259 to your computer and use it in GitHub Desktop.
Aurelia MultiStepView Demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<require from="nav-bar.html"></require> | |
<nav-bar router.bind="router"></nav-bar> | |
<div class="page-host"> | |
<router-view></router-view> | |
</div> | |
</template> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class App { | |
configureRouter(config, router) { | |
config.title = 'Aurelia'; | |
config.map([ | |
{ route: 'home', name: 'home', moduleId: 'home', nav: true, title: 'Home' }, | |
{ route: ['', 'register'], name: 'register', moduleId: 'register', nav: true, title: 'Register' }, | |
{ route: 'register-complete', name: 'register-complete', moduleId: 'register-complete', title: 'Registration Complete' } | |
]); | |
this.router = router; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<h2>Home</h2> | |
</template> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class Home { | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<title>Aurelia</title> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<link rel="stylesheet" href="styles.css"> | |
</head> | |
<body aurelia-app="main"> | |
<h1>Loading...</h1> | |
<script src="https://jdanyow.github.io/rjs-bundle/node_modules/requirejs/require.js"></script> | |
<script src="https://jdanyow.github.io/rjs-bundle/config.js"></script> | |
<script src="https://jdanyow.github.io/rjs-bundle/bundles/aurelia.js"></script> | |
<script src="https://jdanyow.github.io/rjs-bundle/bundles/babel.js"></script> | |
<script> | |
require(['aurelia-bootstrapper']); | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function configure(aurelia) { | |
aurelia.use | |
.standardConfiguration() | |
.developmentLogging() | |
.plugin('aurelia-validation') | |
aurelia.start().then(() => aurelia.setRoot()); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<multi-step-view-header> | |
<h2>${heading}</h2> | |
<span>${currentStep} of ${totalSteps}</span> | |
</multi-step-view-header> | |
<multi-step-view-body> | |
<compose view-model="${currentViewModelPath}" model.bind="model" compose.ref="composeRef" containerless></compose> | |
</multi-step-view-body> | |
<multi-step-view-footer> | |
<div> | |
<button click.delegate="cancel()">Cancel</button> | |
</div> | |
<div> | |
<button if.bind="backButtonActive" click.delegate="back()">Back</button> | |
<button if.bind="nextButtonActive" click.delegate="next()">Next</button> | |
<button if.bind="completeButtonActive" click.delegate="complete({multiStepViewData: model})">Finish</button> | |
</div> | |
</multi-step-view-footer> | |
</template> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {bindable} from 'aurelia-framework'; | |
export class MultiStepViewCustomElement { | |
@bindable cancel; | |
@bindable complete; | |
@bindable heading; | |
@bindable viewModels; | |
backButtonActive = false; | |
completeButtonActive = false; | |
nextButtonActive = true; | |
currentViewModelPath; | |
currentStep = 1; | |
totalSteps = 0; | |
composeRef; | |
model = {}; | |
bind() { | |
if (!this.cancel) { | |
throw new Error('bindable property `cancel` must be defined on MultiStepViewCustomElement'); | |
} | |
if (!this.complete) { | |
throw new Error('bindable property `complete` must be defined on MultiStepViewCustomElement'); | |
} | |
if (!this.viewModels) { | |
throw new Error('bindable property `viewModels` must be defined on MultiStepViewCustomElement'); | |
} | |
this.totalSteps = this.viewModels.length; | |
this._update(); | |
} | |
back() { | |
this.currentStep--; | |
this._update(); | |
} | |
next() { | |
this._isValidView() | |
.then(isValid => { | |
if (isValid) { | |
this.currentStep++; | |
this._update(); | |
} | |
}); | |
} | |
_update() { | |
this._setButtons(); | |
this._setViewModel(); | |
} | |
_setViewModel() { | |
this.currentViewModelPath = this.viewModels[this.currentStep - 1]; | |
} | |
_setButtons() { | |
this.backButtonActive = this.currentStep > 1; | |
this.nextButtonActive = this.currentStep < this.totalSteps; | |
this.completeButtonActive = this.currentStep === this.totalSteps; | |
} | |
_isValidView() { | |
if (!this.composeRef.currentViewModel.isValid) { | |
throw new Error(`${this.composeRef.viewModel} must implement an isValid method returning a boolean`); | |
} | |
return this.composeRef.currentViewModel.isValid(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<h2>Registration Complete</h2> | |
</template> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class RegisterComplete { | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<form> | |
<div class="form-group" validation-errors.bind="firstNameErrors"> | |
<label class="control-label" for="first-name">First Name</label> | |
<input type="text" id="first-name" value.bind="firstName & validate"> | |
<span class="help-block" repeat.for="errorInfo of firstNameErrors"> | |
${errorInfo.error.message} | |
</span> | |
</div> | |
<div class="form-group" validation-errors.bind="lastNameErrors"> | |
<label for="last-name">Last Name</label> | |
<input type="text" id="last-name" value.bind="lastName & validate"> | |
<span class="help-block" repeat.for="errorInfo of lastNameErrors"> | |
${errorInfo.error.message} | |
</span> | |
</div> | |
</form> | |
</template> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {inject, NewInstance} from 'aurelia-dependency-injection'; | |
import {ValidationRules} from 'aurelia-validation'; | |
import {ValidationController, validateTrigger} from 'aurelia-validation'; | |
@inject(NewInstance.of(ValidationController)) | |
export class RegisterStepOne { | |
firstName = ''; | |
lastName = ''; | |
controller = null; | |
constructor(controller) { | |
this.controller = controller; | |
this.controller.validateTrigger = validateTrigger.blur; | |
} | |
activate(model) { | |
this.model = model; | |
this._prepopulate(); | |
} | |
isValid() { | |
return this.controller.validate() | |
.then(errors => { | |
if (errors.length) return false; | |
this._updateModel(); | |
return true; | |
}); | |
} | |
_prepopulate() { | |
this.firstName = this.model.firstName; | |
this.lastName = this.model.lastName; | |
} | |
_updateModel() { | |
this.model.firstName = this.firstName.trim(); | |
this.model.lastName = this.lastName.trim(); | |
} | |
} | |
ValidationRules | |
.ensure('firstName').required() | |
.ensure('lastName').required() | |
.on(RegisterStepOne); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<p>Please check your details...</p> | |
<dl> | |
<dt>Name</dt> | |
<dd>${model.firstName} ${model.lastName}</dd> | |
<dt>Email</dt> | |
<dd>${model.email}</dd> | |
</dl> | |
</template> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class RegisterStepThree { | |
isValid() { | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<p>Hi ${model.firstName}, please provide your email address...</p><br> | |
<form> | |
<div class="form-group" validation-errors.bind="emailErrors"> | |
<label class="control-label" for="email">Email</label> | |
<input type="email" id="email" value.bind="email & validate"> | |
<span class="help-block" repeat.for="errorInfo of emailErrors"> | |
${errorInfo.error.message} | |
</span> | |
</div> | |
</form> | |
</template> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {inject, NewInstance} from 'aurelia-dependency-injection'; | |
import {ValidationRules} from 'aurelia-validation'; | |
import {ValidationController, validateTrigger} from 'aurelia-validation'; | |
@inject(NewInstance.of(ValidationController)) | |
export class RegisterStepTwo { | |
email = ''; | |
constructor(controller) { | |
this.controller = controller; | |
this.controller.validateTrigger = validateTrigger.blur; | |
} | |
activate(model) { | |
this.model = model; | |
this._prepopulate(); | |
} | |
isValid() { | |
return this.controller.validate() | |
.then(errors => { | |
if (errors.length) return false; | |
this._updateModel(); | |
return true; | |
}); | |
} | |
_prepopulate() { | |
this.email = this.model.email; | |
} | |
_updateModel() { | |
this.model.email = this.email.trim(); | |
} | |
} | |
ValidationRules | |
.ensure('email').required().email() | |
.on(RegisterStepTwo); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<require from="multi-step-view"></require> | |
<multi-step-view | |
view-models.bind="viewModels" | |
cancel.call="multiStepViewCancel()" | |
complete.call="multiStepViewComplete(multiStepViewData)" | |
heading.bind="'Register'"> | |
</multi-step-view> | |
</template> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {inject} from 'aurelia-framework'; | |
import {Router} from 'aurelia-router'; | |
@inject(Router) | |
export class Register { | |
viewModels = [ | |
'register-step-one', | |
'register-step-two', | |
'register-step-three' | |
]; | |
constructor(router) { | |
this.router = router; | |
} | |
multiStepViewCancel() { | |
this.router.navigate('home'); | |
} | |
multiStepViewComplete(multiStepViewData) { | |
// TODO do something with data | |
this.router.navigate('register-complete'); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
:root { | |
--accent: rgba(236,12,104,.8); | |
--white: #fff; | |
--black: #000; | |
--grey-light: #666; | |
--grey-medium: #444; | |
--grey-dark: #333; | |
--blue-light: #8ebbdc; | |
--blue-medium: #3c90cc; | |
--blue-dark: #27638e; | |
--blue-deep: #205377; | |
--default-font-size: 18px; | |
--default-border-radius: 4px; | |
--default-border-width: 1px; | |
--default-border-color: #555; | |
--default-border: var(--default-border-width) solid var(--default-border-color); | |
--navigation-bgc: var(--grey-light); | |
--navigation-item-hover-bgc: var(--grey-medium); | |
--navigation-item-active-bgc: var(--accent); | |
--navigation-item-border-color: var(--default-border-color); | |
} | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
} | |
body { | |
font-family: sans-serif; | |
color: var(--grey-dark); | |
font-size: var(--default-font-size); | |
} | |
p { | |
margin: .5em 0; | |
} | |
ul { | |
overflow: hidden; | |
list-style-type: none; | |
} | |
a { | |
display: inline-block; | |
text-decoration: none; | |
} | |
.page-host { | |
margin: 2em; | |
} | |
nav { | |
display: block; | |
background-color: var(--navigation-bgc); | |
} | |
nav li:not(.active):hover { | |
background-color: var(--navigation-item-hover-bgc); | |
} | |
nav li { | |
float: left; | |
border-right: var(--default-border-width) solid var(--navigation-item-border-color); | |
} | |
nav a { | |
padding: 1em 2em; | |
color: var(--white); | |
} | |
nav .active { | |
background-color: var(--navigation-item-active-bgc); | |
} | |
button { | |
padding: 0.5em 1em; | |
color: var(--white); | |
background-color: var(--grey-light); | |
border: 4px solid var(--grey-light); | |
border-radius: var(--default-border-radius); | |
font-size: var(--default-font-size); | |
font-weight: bold; | |
} | |
button:hover { | |
border: 4px solid var(--grey-medium); | |
} | |
dl { | |
margin: 1em 0; | |
} | |
dt { | |
color: var(--blue-light); | |
} | |
dd { | |
margin: .5em 0; | |
padding: .5em; | |
background-color: var(--blue-deep); | |
border-radius: var(--default-border-radius); | |
word-wrap: break-word; | |
} | |
/* forms | |
------------------------------*/ | |
form { | |
width: 100%; | |
} | |
.form-group { | |
margin-bottom: 2em;; | |
} | |
label { | |
display: block; | |
margin-bottom: .5em; | |
font-size: 20px; | |
} | |
input { | |
padding: .5em; | |
width: 100%; | |
border: none; | |
border-radius: var(--default-border-radius); | |
font-size: 100%; | |
} | |
.help-block { | |
display: inline-block; | |
margin-top: 8px; | |
color: var(--blue-light); | |
} | |
.help-block:before { | |
margin-right: 4px; | |
content: "\02718"; | |
} | |
/* | |
multi-step-view | |
------------------------------*/ | |
multi-step-view { | |
display: flex; | |
flex-direction: column; | |
margin: 0 auto; | |
width: 500px; | |
min-height: 400px; | |
background-color: var(--blue-dark); | |
color: var(--white); | |
} | |
multi-step-view-header, | |
multi-step-view-body, | |
multi-step-view-footer { | |
display: flex; | |
padding: 2em; | |
} | |
multi-step-view-header, | |
multi-step-view-footer { | |
justify-content: space-between; | |
} | |
multi-step-view-body { | |
flex: auto; | |
flex-direction: column; | |
} | |
multi-step-view-header { | |
background-color: var(--grey-medium); | |
} | |
multi-step-view-footer { | |
background-color: var(--blue-medium); | |
} | |
multi-step-view button { | |
border: 4px solid var(--blue-dark); | |
background-color: var(--blue-dark); | |
} | |
multi-step-view button:hover { | |
border: 4px solid var(--blue-deep); | |
} | |
multi-step-view-header span { | |
padding: 8px; | |
border-radius: var(--default-border-radius); | |
background-color: var(--grey-light); | |
} | |
/* ai-dialog | |
------------------------------*/ | |
ai-dialog-overlay.active { | |
opacity: 0.5 !important; | |
background-color: var(--black); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment