Skip to content

Instantly share code, notes, and snippets.

@robu3
Last active August 29, 2015 14:05
Show Gist options
  • Save robu3/07f908d29bad74a99e11 to your computer and use it in GitHub Desktop.
Save robu3/07f908d29bad74a99e11 to your computer and use it in GitHub Desktop.
Custom version of the ng-repeat directive, for learning purposes
// Implement our own "repeater" directive
// Note that Angular implicitly converts camelCase to dash-separated values, e.g.,
// myRepeater => my-repeater
app.directive("myRepeater", function () {
var directive = {
restrict: "A",
transclude: "element",
priority: 1000,
terminal: true,
// The compile function is where the magic happens, as they say.
// This is where we use the provided expression and the scope to
// build the resulting DOM elements.
compile: function myRepeaterCompile($element, $attr) {
// $attr will contain the attribute information for the element.
// It will have a property for our directive, using its name: myRepeater
var expression = $attr.myRepeater,
regex = /^(\w+) in (\w+)$/;
console.log("provided expression: " + expression);
// Now we need to validate and parse the expression
var matches = regex.exec(expression);
if (matches !== null) {
var itemName = matches[1],
collectionName = matches[2],
parent = $element.parent(),
elements = [];
// We need to return a linker function,
// a function responsible for registering DOM listeners and updating it as well.
// Our linker function will be very basic, simply iterating over the variable
// named by `collectionName` in our current scope, "killing and refilling" all
// elements every time the collection changes.
return function ($scope, iElement, iAttrs, controller, transclude) {
$scope.$watchCollection(collectionName, function (collection) {
var i;
console.log("myRepeater collection changed: " + collectionName, collection);
if (angular.isArray(collection)) {
// we destroy all of the elements
// and their associated scope everytime the collection changes
if (elements.length > 0) {
for (i = 0; i < elements.length; i++) {
elements[i].el.remove();
elements[i].scope.$destroy();
}
elements = [];
}
for (i = 0; i < collection.length; i++) {
var itemScope = $scope.$new();
itemScope[itemName] = collection[i];
transclude(itemScope, function (clone) {
parent.append(clone);
var block = {};
block.el = clone;
block.scope = itemScope;
elements.push(block);
});
}
}
else {
console.log("myRepeater can only iterate arrays: " + collectionName);
}
});
};
}
else {
console.log("Invalid expression: " + expression);
}
}
};
return directive;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment