Created
May 30, 2020 03:51
-
-
Save 3cp/540da5c0fefe80ce95cd0c33d5f21040 to your computer and use it in GitHub Desktop.
Aurelia demo: binding system
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> | |
<meta charset="utf-8"> | |
<title>Dumber Gist</title> | |
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"> | |
<link | |
href="https://aurelia.io/styles/aurelia-sandbox.css" | |
rel="stylesheet" | |
type="text/css" | |
/> | |
<base href="/"> | |
</head> | |
<!-- | |
Dumber gist uses dumber bundler, the default bundle file | |
is /dist/entry-bundle.js. | |
The starting module is pointed to aurelia-bootstrapper | |
(data-main attribute on script) for Aurelia, | |
The aurelia bootstrapper then loads up user module "main" | |
(aurelia-app attribute on <body>) which is your src/main.ts. | |
--> | |
<body aurelia-app="main"> | |
<script src="/dist/entry-bundle.js" data-main="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
{ | |
"dependencies": { | |
"aurelia-bootstrapper": "^2.3.3" | |
} | |
} |
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
.expression-input { | |
width: 100%; | |
margin-top: 10px; | |
margin-bottom: 10px; | |
} | |
.expression-well { | |
background: #fff; | |
padding: 5px 10px; | |
border-radius: 4px; | |
border: 1px solid #70519e; | |
box-shadow: inset 0 1px 2px 0 rgba(0, 0, 0, 0.4), | |
0 1px 0 0 rgba(255, 255, 255, 0.2); | |
} |
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="./app.css"></require> | |
<require from="./expression"></require> | |
<button | |
repeat.for="example of examples" | |
click.delegate="expressionString = example.expression" | |
> | |
${example.name} | |
</button> | |
<h3>Binding Expression</h3> | |
<input | |
class="expression-input" | |
type="text" | |
value.bind="expressionString" | |
placeholder="Enter binding expresson..."> | |
<h3>AST</h3> | |
<div class="expression-well" if.bind="value"> | |
<expression value.bind="value"></expression> | |
</div> | |
${error} | |
</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, observable, Parser } from "aurelia-framework"; | |
@inject(Parser) | |
export class App { | |
value = null; | |
parser; | |
error; | |
expression; | |
@observable expressionString: string; | |
examples = [ | |
{ name: "Basic Property", expression: `firstName` }, | |
{ name: "Property Path", expression: `person.firstName` }, | |
{ name: "Conditional", expression: `isActive ? 'active' : ''` }, | |
{ name: "Array Index", expression: `myArray[index]` }, | |
{ name: "Binary", expression: `x * y` }, | |
{ name: "Object Literal", expression: `{ x: 3, y: height, z: depth }` }, | |
{ name: "Literal Array", expression: `[a, 1, 'hello', null, undefined]` }, | |
{ name: "Call Method", expression: "save(entity)" }, | |
{ name: "Assignment", expression: "width = rangeInput.value" }, | |
{ | |
name: "Value Converter", | |
expression: `startDate | dateFormat:'MM/dd/yyyy'` | |
}, | |
{ name: "Binding Behavior", expression: `lastName & updateTrigger:'blur'` }, | |
{ | |
name: "Kitchen Sink", | |
expression: `getPosts({ start: minDate, end: maxDate })[0].timestamp | timeAgo & signal:'tick'` | |
} | |
]; | |
constructor(parser) { | |
this.parser = parser; | |
this.expressionString = this.examples[0].expression; | |
} | |
expressionStringChanged(newValue, oldValue) { | |
this.error = ""; | |
this.expression = null; | |
try { | |
this.value = { role: "Root", expression: this.parser.parse(newValue) }; | |
} catch (e) { | |
this.value = null; | |
this.error = e.toString(); | |
} | |
} | |
} |
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
ul.expression-tree { | |
padding: 0; | |
margin: 0; | |
list-style-type: none; | |
position: relative; | |
font-family: sans-serif; | |
} | |
ul.expression-tree li { | |
list-style-type: none; | |
border-left: 2px solid #808080; | |
margin-left: 1em; | |
} | |
ul.expression-tree li div { | |
padding-left: 1em; | |
position: relative; | |
} | |
ul.expression-tree li div::before { | |
content: ""; | |
position: absolute; | |
top: 0; | |
left: -2px; | |
bottom: 50%; | |
width: 0.75em; | |
border: 2px solid #808080; | |
border-top: 0 none transparent; | |
border-right: 0 none transparent; | |
} | |
ul.expression-tree > li:last-child { | |
border-left: 2px solid transparent; | |
} | |
.expression-type { | |
color: blue; | |
font-weight: bold; | |
} | |
.expression-role { | |
color: green; | |
} | |
.expression-text { | |
font-family: monospace; | |
color: #808080; | |
} |
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="./expression.css"></require> | |
<ul class="expression-tree"> | |
<div> | |
<span class="expression-type">${type}</span> | |
<span class="expression-role">[${value.role}]</span> | |
<code class="expression-text">${value.expression}</code> | |
</div> | |
<li repeat.for="child of children"> | |
<expression value.bind="child"></expression> | |
</li> | |
</ul> | |
</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 { | |
AccessThis, | |
AccessScope, | |
AccessMember, | |
AccessKeyed, | |
Assign, | |
Binary, | |
BindingBehavior, | |
CallFunction, | |
CallMember, | |
CallScope, | |
Conditional, | |
LiteralPrimitive, | |
LiteralArray, | |
LiteralObject, | |
LiteralString, | |
Unary, | |
ValueConverter, | |
bindable, | |
containerless | |
} from "aurelia-framework"; | |
@containerless | |
export class Expression { | |
@bindable value; | |
type = null; | |
children = null; | |
valueChanged({ role, expression }) { | |
if (expression instanceof AccessThis) { | |
this.type = "AccessThis"; | |
this.children = null; | |
} else if (expression instanceof AccessScope) { | |
this.type = "AccessScope"; | |
this.children = null; | |
} else if (expression instanceof AccessMember) { | |
this.type = "AccessMember"; | |
this.children = [{ role: "Object", expression: expression.object }]; | |
} else if (expression instanceof AccessKeyed) { | |
this.type = "AccessKeyed"; | |
this.children = [ | |
{ role: "Object", expression: expression.object }, | |
{ role: "Key", expression: expression.key } | |
]; | |
} else if (expression instanceof Assign) { | |
this.type = "Assign"; | |
this.children = [ | |
{ role: "Target", expression: expression.target }, | |
{ role: "Value", expression: expression.value } | |
]; | |
} else if (expression instanceof Binary) { | |
this.type = "Binary"; | |
this.children = [ | |
{ role: "Left", expression: expression.left }, | |
{ role: "Right", expression: expression.right } | |
]; | |
} else if (expression instanceof BindingBehavior) { | |
this.type = "BindingBehavior"; | |
this.children = [ | |
{ role: "Target", expression: expression.expression }, | |
...expression.args.map(x => ({ role: "Argument", expression: x })) | |
]; | |
} else if (expression instanceof CallFunction) { | |
this.type = "CallFunction"; | |
this.children = [ | |
{ role: "Function", expression: expression.func }, | |
...expression.args.map(x => ({ role: "Argument", expression: x })) | |
]; | |
} else if (expression instanceof CallMember) { | |
this.type = "CallMember"; | |
this.children = [ | |
{ role: "Object", expression: expression.object }, | |
...expression.args.map(x => ({ role: "Argument", expression: x })) | |
]; | |
} else if (expression instanceof CallScope) { | |
this.type = "CallScope"; | |
this.children = expression.args.map(x => ({ | |
role: "Argument", | |
expression: x | |
})); | |
} else if (expression instanceof Conditional) { | |
this.type = "Conditional"; | |
this.children = [ | |
{ role: "Condition", expression: expression.condition }, | |
{ role: "True-Value", expression: expression.yes }, | |
{ role: "False-Value", expression: expression.no } | |
]; | |
} else if (expression instanceof LiteralPrimitive) { | |
this.type = "LiteralPrimitive"; | |
this.children = null; | |
} else if (expression instanceof LiteralString) { | |
this.type = "LiteralString"; | |
this.children = null; | |
} else if (expression instanceof LiteralArray) { | |
this.type = "LiteralArray"; | |
this.children = expression.elements.map(x => ({ | |
role: "Element", | |
expression: x | |
})); | |
} else if (expression instanceof LiteralObject) { | |
this.type = "LiteralObject"; | |
this.children = expression.values.map(x => ({ | |
role: "Property Value", | |
expression: x | |
})); | |
} else if (expression instanceof Unary) { | |
this.type = "Unary"; | |
this.children = [{ role: "Target", expression: expression.expression }]; | |
} else if (expression instanceof ValueConverter) { | |
this.type = "ValueConverter"; | |
this.children = [ | |
{ role: "Target", expression: expression.allArgs[0] }, | |
...expression.args.map(x => ({ role: "Argument", expression: x })) | |
]; | |
} else { | |
this.type = "Unknown"; | |
this.children = null; | |
} | |
} | |
} |
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 {Aurelia} from 'aurelia-framework'; | |
export function configure(aurelia: Aurelia) { | |
aurelia.use | |
.standardConfiguration() | |
.developmentLogging('info'); | |
aurelia.start().then(() => aurelia.setRoot()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment