Skip to content

Instantly share code, notes, and snippets.

@AdamWillden
Last active June 1, 2017 20:46
Show Gist options
  • Save AdamWillden/9740628041e33a501f03f200a5dda7ea to your computer and use it in GitHub Desktop.
Save AdamWillden/9740628041e33a501f03f200a5dda7ea to your computer and use it in GitHub Desktop.
<template>
<require from="./dynamic-element"></require>
<button click.trigger="changeModelOnTextBox()">Change Text</button>
<button click.trigger="toggle()">Toggle</button>
<div if.bind="show">
Dynamic controls:
<div repeat.for="control of controls">
${control.label}
<dynamic-element type.bind="control.type" model.bind="control.model"></dynamic-element>
<div>
control.model = ${control.model}
</div>
</div>
</div>
</template>
import { DatePicker } from './date-picker';
import { TextBox } from './text-box';
export class App {
show = true;
controls = [
{label: 'Entry Date', type: DatePicker, model: '2017-01-01' },
{label: 'Code', type: TextBox, model: 'This is some other text'}
];
toggle() {
this.show = !this.show;
}
changeModelOnTextBox() {
let texboxIndex = this.controls.findIndex(x => x.label === 'Code');
this.controls[texboxIndex].model = 'I changed the model!';
}
}
<template>
<input type="date" value.bind="model" />
</template>
import { bindable, bindingMode } from 'aurelia-framework';
export class DatePicker {
@bindable({ defaultBindingMode: bindingMode.twoWay }) model;
bind() {
alert("bind");
}
attached() {
//alert("attached");
}
detached() {
//alert("detached");
}
}
import { bindingMode } from 'aurelia-binding';
import { inject, Container } from 'aurelia-dependency-injection';
import { bindable, noView, ViewCompiler, ViewResources, ViewSlot } from 'aurelia-templating';
import { ResourceLoader } from './resource-loader';
const twoWayBinding = { defaultBindingMode: bindingMode.twoWay };
@noView()
@inject(
Container,
ViewResources,
ViewCompiler,
ViewSlot,
ResourceLoader,
)
export class DynamicElement {
resourceLoadPromise;
@bindable() type;
@bindable(twoWayBinding) model;
get bindingContext() {
return { model: this.model };
}
get tagName() {
return this.type.name.split(/(?=[A-Z])/).join('-').toLowerCase();
}
get html() {
return `<${this.tagName} model.bind="model"></${this.tagName}>`;
}
constructor(
container,
resources,
viewCompiler,
viewSlot,
resourceLoader,
) {
this.container = container;
this.resources = resources;
this.viewCompiler = viewCompiler;
this.viewSlot = viewSlot;
this.resourceLoader = resourceLoader;
}
bind() {
this.resourceLoader.ensureLoaded(this.type, this.resources, this.container);
}
attached() {
this.resourceLoader
.awaitLoad(this.type, this.resources)
.then(() => {
var viewFactory = this.viewCompiler.compile(`<template>${this.html}</template>`, this.resources);
var view = viewFactory.create(this.container);
//view.bind(this.bindingContext);
this.viewSlot.add(view);
});
}
}
<!doctype html>
<html>
<head>
<title>Aurelia</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body aurelia-app="main">
<h1>Loading...</h1>
<script src="https://cdn.rawgit.com/jdanyow/aurelia-bundle/v1.0.3/jspm_packages/system.js"></script>
<script src="https://cdn.rawgit.com/jdanyow/aurelia-bundle/v1.0.3/config.js"></script>
<script>
System.import('aurelia-bootstrapper');
</script>
</body>
</html>
export function configure(aurelia) {
aurelia.use
.standardConfiguration()
.developmentLogging()
.globalResources([
//'./date-picker',
//'./text-box'
]);
aurelia.start().then(a => a.setRoot());
}
import { HtmlBehaviorResource } from 'aurelia-templating';
export class ResourceLoader {
loading = new Map();
getTagName(type) {
return type.name.split(/(?=[A-Z])/).join('-').toLowerCase();
}
ensureLoaded(type, resources, container) {
if (this.isRegistered(type, resources)) {
return this.awaitLoad(type, resources);
}
let resource = HtmlBehaviorResource.convention(type.name + 'CustomElement');
resource.initialize(container, type);
resource.register(resources)
let promise = resource.load(container, type)
.then(() => this.loading.delete(type));
this.loading.set(type, promise);
return promise;
}
isRegistered(type, resources) {
let tagName = this.getTagName(type);
return !!resources.elements[tagName];
}
awaitLoad(type, resources) {
console.log('await load');
if (!this.isRegistered(type, resources)) {
return Promise.reject();
}
let promise = this.loading.get(type);
console.log('promise', promise);
return promise || Promise.resolve();
}
}
<template>
<input type="text" value.bind="model" />
</template>
import { bindable, bindingMode } from 'aurelia-framework';
export class TextBox {
@bindable({ defaultBindingMode: bindingMode.twoWay }) model;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment