aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMisko Hevery2010-03-22 15:46:34 -0700
committerMisko Hevery2010-03-22 15:46:34 -0700
commitb4561ff951ff452e55e820f6f8344dc2668cfd90 (patch)
treeca454e5edcf0fbe04a32ff9c950cce9be701e43b /src
parent84552f7f8ac3f39c4dbd7d946ae2938d63302840 (diff)
downloadangular.js-b4561ff951ff452e55e820f6f8344dc2668cfd90.tar.bz2
ng-repeat works
Diffstat (limited to 'src')
-rw-r--r--src/Angular.js25
-rw-r--r--src/Compiler.js16
-rw-r--r--src/directives.js36
3 files changed, 61 insertions, 16 deletions
diff --git a/src/Angular.js b/src/Angular.js
index cfffab04..1549e7a7 100644
--- a/src/Angular.js
+++ b/src/Angular.js
@@ -181,15 +181,32 @@ function escapeAttr(html) {
function bind(_this, _function) {
var curryArgs = slice.call(arguments, 2, arguments.length);
- if (!_this)
- throw "Missing this";
- if (!_.isFunction(_function))
- throw "Missing function";
return function() {
return _function.apply(_this, curryArgs.concat(slice.call(arguments, 0, arguments.length)));
};
}
+function bindTry(_this, _function) {
+ var args = arguments,
+ last = args.length - 1,
+ curryArgs = slice.call(args, 2, last),
+ exceptionHandler = args[last];
+ return function() {
+ try {
+ return _function.apply(_this, curryArgs.concat(slice.call(arguments, 0, arguments.length)));
+ } catch (e) {
+ if (e = exceptionHandler(e)) throw e;
+ }
+ };
+}
+
+function errorHandlerFor(element) {
+ return function(error){
+ element.attr('ng-error', angular.toJson(error));
+ element.addClass('ng-exception');
+ };
+}
+
function outerHTML(node) {
var temp = document.createElement('div');
temp.appendChild(node);
diff --git a/src/Compiler.js b/src/Compiler.js
index 5c650204..ece44805 100644
--- a/src/Compiler.js
+++ b/src/Compiler.js
@@ -107,6 +107,20 @@ JQLite.prototype = {
this.element.parentNode.insertBefore(jqLite(element).element, this.element.nextSibling);
},
+ hasClass: function(selector) {
+ var className = " " + selector + " ";
+ if ( (" " + this.element.className + " ").replace(/[\n\t]/g, " ").indexOf( className ) > -1 ) {
+ return true;
+ }
+ return false;
+ },
+
+ addClass: function( selector ) {
+ if (!this.hasClass(selector)) {
+ this.element.className += ' ' + selector;
+ }
+ },
+
attr: function(name, value){
var e = this.element;
if (isObject(name)) {
@@ -201,7 +215,7 @@ Compiler.prototype = {
exclusive = true;
directiveQueue = [];
}
- directiveQueue.push(bind(selfApi, directive, value, element));
+ directiveQueue.push(bindTry(selfApi, directive, value, element, errorHandlerFor(element)));
}
});
diff --git a/src/directives.js b/src/directives.js
index 66a5e864..8047cdbd 100644
--- a/src/directives.js
+++ b/src/directives.js
@@ -10,7 +10,7 @@ angularDirective("ng-eval", function(expression){
};
});
-angular.directive("ng-bind", function(expression){
+angularDirective("ng-bind", function(expression){
return function(element) {
this.$watch(expression, function(value){
element.text(value);
@@ -18,23 +18,36 @@ angular.directive("ng-bind", function(expression){
};
});
-angular.directive("ng-bind-attr", function(expression){
+angularDirective("ng-bind-attr", function(expression){
return function(element){
this.$watch(expression, bind(element, element.attr));
};
});
-angular.directive("ng-non-bindable", function(){
+angularDirective("ng-non-bindable", function(){
this.descend(false);
});
-angular.directive("ng-repeat", function(expression, element){
+angularDirective("ng-repeat", function(expression, element){
var reference = this.reference("ng-repeat: " + expression),
r = element.removeAttr('ng-repeat'),
template = this.compile(element),
- path = expression.split(' in '),
- lhs = path[0],
- rhs = path[1];
+ match = expression.match(/^\s*(.+)\s+in\s+(.*)\s*$/),
+ lhs, rhs, valueIdent, keyIdent;
+ if (! match) {
+ throw "Expected ng-repeat in form of 'item in collection' but got '" +
+ expression + "'.";
+ }
+ lhs = match[1];
+ rhs = match[2];
+ match = lhs.match(/^([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\)$/);
+ if (!match) {
+ throw "'item' in 'item in collection' should be identifier or (key, value) but got '" +
+ keyValue + "'.";
+ }
+ valueIdent = match[3] || match[1];
+ keyIdent = match[2];
+
var parent = element.parent();
element.replaceWith(reference);
return function(){
@@ -42,7 +55,7 @@ angular.directive("ng-repeat", function(expression, element){
currentScope = this;
this.$addEval(rhs, function(items){
var index = 0, childCount = children.length, childScope, lastElement = reference;
- foreach(items, function(value, key){
+ foreach(items || [], function(value, key){
if (index < childCount) {
// reuse existing child
childScope = children[index];
@@ -55,7 +68,8 @@ angular.directive("ng-repeat", function(expression, element){
lastElement.after(childScope.element);
children.push(childScope);
}
- childScope.scope.set(lhs, value);
+ childScope.scope.set(valueIdent, value);
+ if (keyIdent) childScope.scope.set(keyIdent, key);
childScope.scope.updateView();
lastElement = childScope.element;
index ++;
@@ -86,7 +100,7 @@ angular.directive("ng-repeat", function(expression, element){
//ng-show, ng-hide
-angular.directive("action", function(expression, element){
+angularDirective("action", function(expression, element){
return function(){
var self = this;
jQuery(element).click(function(){
@@ -97,7 +111,7 @@ angular.directive("action", function(expression, element){
//ng-watch
// <div ng-watch="$anchor.book: book=Book.get();"/>
-angular.directive("watch", function(expression, element){
+angularDirective("watch", function(expression, element){
var watches = {
'lhs':'rhs'
}; // parse