Skip to content

Instantly share code, notes, and snippets.

@axefrog
Created April 13, 2015 23:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save axefrog/ba892af4e281e6c70c4a to your computer and use it in GitHub Desktop.
Save axefrog/ba892af4e281e6c70c4a to your computer and use it in GitHub Desktop.
Aurelia self-referencing view causing stack overflow error
<template>
<require from="./linked-data"></require>
<table>
<tbody>
<tr repeat.for="pair of pairs()">
<td>${pair.predicate}</td>
<td>
<linked-data subject.bind="this" predicate.bind="pair.predicate" value.bind="pair.value"></linked-data>
</td>
</tr>
</tbody>
</table>
</template>
// The subset of functionality for dynamically composing a child view is adapted from Aurelia's
// compose element: https://github.com/aurelia/templating-resources/blob/master/src/compose.js
import {
LogManager, Container, CompositionEngine, ViewSlot, ViewResources, ConventionalViewStrategy, NoViewStrategy,
bindable, inject, noView, skipContentProcessing
} from 'aurelia-framework';
import ExtensionRegistry from '../extension-registry';
import ResourceManager from '../resource-manager';
@noView
@skipContentProcessing
@bindable('subject')
@bindable('predicate')
@bindable('value')
@inject(ExtensionRegistry, ResourceManager, Element, Container, CompositionEngine, ViewSlot, ViewResources)
export class LinkedDataCustomElement
{
constructor(extensions, resourceManager, element, container, compositionEngine, viewSlot, viewResources) {
this.log = LogManager.getLogger('LinkedData View');
this.log.debug('Constructed');
this.extensions = extensions;
this.resourceManager = resourceManager;
this.element = element;
this.container = container;
this.compositionEngine = compositionEngine;
this.viewSlot = viewSlot;
this.viewResources = viewResources;
}
present() {
this.useDefaultView = false;
var renderer = null;
if(this.predicate) {
renderer = this.extensions.get(this.predicate);
}
else if(this.value && typeof this.value === 'object') {
if(this.value['@id']) {
renderer = this.extensions.get(this.value['@id']);
}
else if(this.value['@type']) {
renderer = this.extensions.get(this.value['@type']);
}
if(!renderer) {
this.useDefaultView = true;
return;
}
}
if(!renderer) {
return;
}
var renderFunc = null;
switch(typeof renderer) {
case 'string':
processInstruction(this, { viewModel: renderer, model: this.value });
return;
case 'function':
renderFunc = renderer;
break;
case 'object':
if(renderer.render) {
var self = this;
renderFunc = function() {
return renderer.render.apply(renderer, Array.prototype.slice.call(arguments));
};
}
break;
}
if(!renderFunc) {
return;
}
while(this.element.lastChild) {
this.element.removeChild(this.element.lastChild);
}
var result = renderFunc(this.value, this.element);
if(!result) {
return;
}
switch(typeof result) {
case 'undefined':
return;
case 'string':
this.element.innerText = result;
break;
case 'object':
if(result instanceof Element) {
this.element.appendChild(result);
}
else {
this.element.innerText = result.toString();
}
break;
}
}
activate(value) {
this.value = value;
}
bind(executionContext) {
this.executionContext = executionContext;
if(this.value) {
this.present();
}
}
valueChanged(oldValue, newValue) {
this.present();
}
pairs() {
return Object.keys(this.value)
.map(key => ({
predicate: key,
value: this.value[key]
}));
}
getViewStrategy() {
console.log('cdscsdcsd')
return this.useDefaultView ? null : new NoViewStrategy();
}
}
function processInstruction(composer, instruction){
return composer.compositionEngine.compose(Object.assign(instruction, {
executionContext:composer.executionContext,
container:composer.container,
viewSlot:composer.viewSlot,
viewResources:composer.viewResources,
currentBehavior:composer.currentBehavior
})).then(next => {
composer.currentBehavior = next;
composer.currentViewModel = next ? next.executionContext : null;
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment