Skip to content

Instantly share code, notes, and snippets.

@ajayvikas
Last active October 2, 2016 01:14
Show Gist options
  • Save ajayvikas/c420917c8c57c864d7e5d32760f49077 to your computer and use it in GitHub Desktop.
Save ajayvikas/c420917c8c57c864d7e5d32760f49077 to your computer and use it in GitHub Desktop.
Compose Element Modification
<template>
<require from="./test"></require>
<require from="./compose"></require>
Works with custom element as node name
<br/>
<br/>
<test>
<div slot="slot1">
Some slot content
</div>
</test>
<br/>
<br/>
Does not work with compose element
<br/>
<br/>
<compose view-model="test">
<div slot="slot1">
Some slot content
</div>
</compose>
<br/>
<br/>
Works with custom compose element
<br/>
<br/>
<sk-compose view-model="test">
<div slot="slot1">
Some slot content
</div>
</sk-compose>
</template>
export class App {
message = 'Hello World!';
}
import {
customElement,
bindable,
noView,
ViewResources,
ViewSlot,
CompositionEngine,
View,
CompositionContext,
ViewCompiler,
ViewFactory,
containerless,
processContent,
BehaviorInstruction,
HtmlBehaviorResource, Controller, customAttribute
} from "aurelia-templating";
import {inject, Container} from "aurelia-dependency-injection";
import {TaskQueue} from "aurelia-task-queue";
import {DOM} from "aurelia-pal";
import {metadata} from "aurelia-metadata";
import {LogManager} from "aurelia-framework";
import {Logger} from "aurelia-logging";
const logger:Logger = LogManager.getLogger('sk-compose');
function contentProcessor(compiler:ViewCompiler, resources:ViewResources, node:Node, instruction:BehaviorInstruction):boolean{
if(node instanceof Element){
let templateNode = DOM.createElement('au-content');
templateNode.innerHTML = node.innerHTML;
while(node.childNodes && node.childNodes.length > 0){
node.removeChild(node.childNodes[0]);
}
if(instruction.type['containerless']){
node.appendChild(templateNode);
}else{
node['contentElement'] = templateNode;
}
instruction['skComposeTemplate'] = templateNode;
}
return false;
}
@customElement('sk-compose')
@noView
@containerless()
@inject(Element, Container, ViewSlot, ViewResources, TaskQueue, ViewCompiler, CompositionEngine)
@processContent(contentProcessor)
export class ComposeComponent{
@bindable model;
@bindable viewModel;
view:View;
bindingContext:any;
overrideContext:any;
currentInstruction:CompositionContext;
owningView:View;
constructor(element:Element, container:Container,
viewSlot:ViewSlot, viewResources:ViewResources, taskQueue:TaskQueue,
viewCompiler:ViewCompiler, compositionEngine:CompositionEngine) {
this.element = element;
this.container = container;
this.viewSlot = viewSlot;
this.viewResources = viewResources;
this.taskQueue = taskQueue;
this.viewCompiler = viewCompiler;
this.compositionEngine = compositionEngine;
}
created(owningView: View) {
this.owningView = owningView;
}
bind(bindingContext, overrideContext) {
this.bindingContext = bindingContext;
this.overrideContext = overrideContext;
this.queueTaskIfNecessary();
}
unbind(bindingContext, overrideContext) {
this.bindingContext = null;
this.overrideContext = null;
this.currentInstruction = null;
if(this.view){
this.viewSlot.remove(this.view, true, true);
this.view = null;
}
}
modelChanged(newValue, oldValue) {
this.queueTaskIfNecessary();
}
viewModelChanged(newValue, oldValue) {
this.queueTaskIfNecessary();
}
queueTaskIfNecessary():void{
if (this.currentInstruction) {
this.currentInstruction.model = this.model;
this.currentInstruction.viewModel = this.viewModel;
return;
}
if(this.view){
this.viewSlot.remove(this.view, true, true);
this.view = null;
}
this.currentInstruction = null;
if(this.viewModel){
this.currentInstruction = {
viewModel: this.viewModel,
model: this.model,
bindingContext: this.bindingContext,
overrideContext: this.overrideContext,
owningView: this.owningView,
container: this.container,
viewSlot: this.viewSlot,
viewResources: this.viewResources,
// currentController: this.currentController,
host: this.element['contentElement'] ? this.element['contentElement'] : this.element
};
this.taskQueue.queueMicroTask(() => this.processInstruction());
}
}
processInstruction():void{
if(this.currentInstruction){
this.compositionEngine.createController(this.currentInstruction).then((controller:Controller) => {
let meta:HtmlBehaviorResource = controller ? controller.behavior : null;
if(meta){
this.viewResources.registerElement(meta['elementName'], meta);
let str:string = `<${meta['elementName']}>${this.element['au'].controller.instruction.skComposeTemplate.innerHTML}</${meta['elementName']}>`;
let viewFactory:ViewFactory = this.viewCompiler.compile(`<template>${str}</template>`, this.viewResources);
this.view = viewFactory.create(this.container);
Object.assign(this.overrideContext, this.model);
this.view.bind(this.bindingContext, this.overrideContext);
this.viewSlot.add(this.view);
}else{
logger.error(`Could not create sk-compose element with view-model[${this.viewModel}]`);
}
}, (reason) => {
logger.error(`failed to load controller [${reason}]`);
});
}
this.currentInstruction = null;
}
}
<!doctype html>
<html>
<head>
<title>Aurelia</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body aurelia-app>
<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>
<template style="background-color: green;">
Content Before Slot
<slot name="slot1"></slot>
Content After Slot
</template>
export class TestCustomElement{
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment