Skip to content

Instantly share code, notes, and snippets.

@niieani
Last active May 12, 2016 12:51
Show Gist options
  • Save niieani/6d2d446e55947d564daae507800da5c4 to your computer and use it in GitHub Desktop.
Save niieani/6d2d446e55947d564daae507800da5c4 to your computer and use it in GitHub Desktop.
Aurelia Template Behaviour with repeat-items-changed
<template>
<require from="./attaching-span"></require>
<h1>${message}</h1>
<button click.delegate="addNumber('before')">Add number before</button>
<button click.delegate="addNumber('after')">Add number after</button>
<button click.delegate="addMany('before')">Add many before</button>
<button click.delegate="addMany('after')">Add many after</button>
<div>
<span repeat.for="number of numbers" repeat-items-changed.bind="repeatRendered">${number}</span>
</div>
</template>
import {inject, ObserverLocator, TaskQueue} from 'aurelia-framework';
import {Repeat} from 'aurelia-templating-resources'
@inject(ObserverLocator, TaskQueue)
export class App {
constructor(observerLocator, taskQueue) {
this.message = 'Hello World!';
this.numbers = [];
}
repeatRendered() {
alert('rendered!')
}
addNumber(location) {
const newNumber = this.numbers.length;
if(location == 'before') {
this.numbers.unshift(newNumber);
} else {
this.numbers.push(newNumber);
}
}
addMany(location) {
const newNumber = this.numbers.length;
if(location == 'before') {
this.numbers.unshift(newNumber);
this.numbers.unshift(newNumber);
this.numbers.unshift(newNumber);
this.numbers.unshift(newNumber);
} else {
this.numbers.push(newNumber);
this.numbers.push(newNumber);
this.numbers.push(newNumber);
this.numbers.push(newNumber);
}
}
}
Repeat.prototype._captureAndRemoveItemsChangedBinding = function() {
if (this.viewFactory.viewFactory) {
const instructions = this.viewFactory.viewFactory.instructions;
const instructionIds = Object.keys(instructions);
for (let i = 0; i < instructionIds.length; i++) {
const expressions = instructions[instructionIds[i]].expressions;
if (expressions) {
for (let ii = 0; i < expressions.length; i++) {
if (expressions[ii].targetProperty === 'repeat-items-changed') {
const binding = expressions[ii];
expressions.splice(ii, 1);
return binding;
}
}
}
}
}
}
Repeat.prototype.onItemsChanged = function() {
return this.onItemsChangedBinding ? this.onItemsChangedBinding.sourceExpression.evaluate(this.scope, this.onItemsChangedBinding.lookupFunctions) : null;
}
Repeat.prototype.callOnItemsChanged = function() {
const onItemsChanged = this.onItemsChanged();
if (onItemsChanged) {
this.observerLocator.taskQueue.queueTask(() => {
onItemsChanged();
});
}
}
const itemsChanged = Repeat.prototype.itemsChanged;
Repeat.prototype.itemsChanged = function() {
itemsChanged.call(this);
this.callOnItemsChanged();
}
const handleCollectionMutated = Repeat.prototype.handleCollectionMutated;
Repeat.prototype.handleCollectionMutated = function(collection, changes) {
handleCollectionMutated.call(this, collection, changes);
this.callOnItemsChanged();
}
// TODO: handleInnerCollectionMutated
const bind = Repeat.prototype.bind;
Repeat.prototype.bind = function(bindingContext, overrideContext) {
this.scope = { bindingContext, overrideContext };
this.onItemsChangedBinding = this._captureAndRemoveItemsChangedBinding();
bind.apply(this, arguments);
}
import {inlineView, customElement} from 'aurelia-framework'
@customElement('attaching-span')
@inlineView(`<template><content></content></template>`)
export class AttachingSpan {
attached() {
// you can notify that the element is attached, but the method has to be present
}
}
<!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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment