From af285dd370aa1b6779bf67ac3bdc19da512aaac5 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Tue, 19 Apr 2011 16:34:49 -0700 Subject: Added ng:options directive Closes #301 --- src/Angular.js | 5 +- src/directives.js | 6 +- src/formatters.js | 2 + src/parser.js | 3 +- src/widgets.js | 288 +++++++++++++++++++++++++++++++++++++++++++----------- 5 files changed, 241 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/Angular.js b/src/Angular.js index 26026cf3..b5e7e12f 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -52,8 +52,9 @@ if ('i' !== 'I'.toLowerCase()) { function fromCharCode(code) { return String.fromCharCode(code); } -var $$element = '$element', - $$update = '$update', +var _undefined = undefined, + _null = null, + $$element = '$element', $$scope = '$scope', $$validate = '$validate', $angular = 'angular', diff --git a/src/directives.js b/src/directives.js index 34a1b27d..016ba9fe 100644 --- a/src/directives.js +++ b/src/directives.js @@ -443,10 +443,8 @@ var REMOVE_ATTRIBUTES = { angularDirective("ng:bind-attr", function(expression){ return function(element){ var lastValue = {}; - var updateFn = element.data($$update) || noop; this.$onEval(function(){ - var values = this.$eval(expression), - dirty = noop; + var values = this.$eval(expression); for(var key in values) { var value = compileBindTemplate(values[key]).call(this, element), specialName = REMOVE_ATTRIBUTES[lowercase(key)]; @@ -464,10 +462,8 @@ angularDirective("ng:bind-attr", function(expression){ } else { element.attr(key, value); } - dirty = updateFn; } } - dirty(); }, element); }; }); diff --git a/src/formatters.js b/src/formatters.js index 906db619..b484f26f 100644 --- a/src/formatters.js +++ b/src/formatters.js @@ -204,6 +204,7 @@ angularFormatter.trim = formatter( * @workInProgress * @ngdoc formatter * @name angular.formatter.index + * @deprecated * @description * Index formatter is meant to be used with `select` input widget. It is useful when one needs * to select from a set of objects. To create pull-down one can iterate over the array of object @@ -250,6 +251,7 @@ angularFormatter.trim = formatter( */ +//TODO: delete me since this is replaced by ng:options angularFormatter.index = formatter( function(object, array){ return '' + indexOf(array || [], object); diff --git a/src/parser.js b/src/parser.js index 59d7899a..0c4a391a 100644 --- a/src/parser.js +++ b/src/parser.js @@ -239,6 +239,8 @@ function parser(text, json){ pipeFunction = function (){ throwError("is not valid json", {text:text, index:0}); }; } + //TODO: Shouldn't all of the public methods have assertAllConsumed? + //TODO: I think these should be public as part of the parser api instead of scope.$eval(). return { assignable: assertConsumed(assignable), primary: assertConsumed(primary), @@ -659,4 +661,3 @@ function parser(text, json){ - diff --git a/src/widgets.js b/src/widgets.js index 4245f99c..a9d42bdf 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -166,18 +166,19 @@ function modelAccessor(scope, element) { var expr = element.attr('name'); - var assign; + var exprFn, assignFn; if (expr) { - assign = parser(expr).assignable().assign; - if (!assign) throw new Error("Expression '" + expr + "' is not assignable."); + exprFn = parser(expr).assignable(); + assignFn = exprFn.assign; + if (!assignFn) throw new Error("Expression '" + expr + "' is not assignable."); return { get: function() { - return scope.$eval(expr); + return exprFn(scope); }, set: function(value) { if (value !== undefined) { return scope.$tryEval(function(){ - assign(scope, value); + assignFn(scope, value); }, element); } } @@ -561,64 +562,241 @@ function inputWidgetSelector(element){ angularWidget('input', inputWidgetSelector); angularWidget('textarea', inputWidgetSelector); angularWidget('button', inputWidgetSelector); -angularWidget('select', function(element){ - this.descend(true); - return inputWidgetSelector.call(this, element); -}); +/** + * @workInProgress + * @ngdoc directive + * @name angular.directive.ng:options + * + * @description + * Dynamically generate a list of `