diff options
Diffstat (limited to 'src/directives.js')
| -rw-r--r-- | src/directives.js | 158 |
1 files changed, 91 insertions, 67 deletions
diff --git a/src/directives.js b/src/directives.js index 9aa0d57e..4712f250 100644 --- a/src/directives.js +++ b/src/directives.js @@ -73,7 +73,7 @@ */ angularDirective("ng:init", function(expression){ return function(element){ - this.$tryEval(expression, element); + this.$eval(expression); }; }); @@ -165,19 +165,19 @@ angularDirective("ng:init", function(expression){ </doc:example> */ angularDirective("ng:controller", function(expression){ - this.scope(true); - return function(element){ - var controller = getter(window, expression, true) || getter(this, expression, true); - if (!controller) - throw "Can not find '"+expression+"' controller."; - if (!isFunction(controller)) - throw "Reference '"+expression+"' is not a class."; - this.$become(controller); - }; + this.scope(function(scope){ + var Controller = + getter(scope, expression, true) || + getter(window, expression, true); + assertArgFn(Controller, expression); + return Controller; + }); + return noop; }); /** * @workInProgress + * @deprecated * @ngdoc directive * @name angular.directive.ng:eval * @@ -208,17 +208,18 @@ angularDirective("ng:controller", function(expression){ <doc:scenario> it('should check eval', function(){ expect(binding('obj.divide')).toBe('3'); - expect(binding('obj.updateCount')).toBe('2'); + expect(binding('obj.updateCount')).toBe('1'); input('obj.a').enter('12'); expect(binding('obj.divide')).toBe('6'); - expect(binding('obj.updateCount')).toBe('3'); + expect(binding('obj.updateCount')).toBe('2'); }); </doc:scenario> </doc:example> */ +// TODO(misko): remove me angularDirective("ng:eval", function(expression){ return function(element){ - this.$onEval(expression, element); + this.$observe(expression); }; }); @@ -257,15 +258,26 @@ angularDirective("ng:bind", function(expression, element){ element.addClass('ng-binding'); return function(element) { var lastValue = noop, lastError = noop; - this.$onEval(function() { + this.$observe(function(scope) { + // TODO(misko): remove error handling https://github.com/angular/angular.js/issues/347 var error, value, html, isHtml, isDomElement, - oldElement = this.hasOwnProperty($$element) ? this.$element : undefined; - this.$element = element; - value = this.$tryEval(expression, function(e){ + hadOwnElement = scope.hasOwnProperty('$element'), + oldElement = scope.$element; + // TODO(misko): get rid of $element https://github.com/angular/angular.js/issues/348 + scope.$element = element; + try { + value = scope.$eval(expression); + } catch (e) { + scope.$service('$exceptionHandler')(e); error = formatError(e); - }); - this.$element = oldElement; - // If we are HTML then save the raw HTML data so that we don't + } finally { + if (hadOwnElement) { + scope.$element = oldElement; + } else { + delete scope.$element; + } + } + // If we are HTML than save the raw HTML data so that we don't // recompute sanitization since it is expensive. // TODO: turn this into a more generic way to compute this if (isHtml = (value instanceof HTML)) @@ -289,7 +301,7 @@ angularDirective("ng:bind", function(expression, element){ element.text(value == undefined ? '' : value); } } - }, element); + }); }; }); @@ -301,10 +313,14 @@ function compileBindTemplate(template){ forEach(parseBindings(template), function(text){ var exp = binding(text); bindings.push(exp - ? function(element){ - var error, value = this.$tryEval(exp, function(e){ + ? function(scope, element) { + var error, value; + try { + value = scope.$eval(exp); + } catch(e) { + scope.$service('$exceptionHandler')(e); error = toJson(e); - }); + } elementError(element, NG_EXCEPTION, error); return error ? error : value; } @@ -312,20 +328,30 @@ function compileBindTemplate(template){ return text; }); }); - bindTemplateCache[template] = fn = function(element, prettyPrintJson){ - var parts = [], self = this, - oldElement = this.hasOwnProperty($$element) ? self.$element : undefined; - self.$element = element; - for ( var i = 0; i < bindings.length; i++) { - var value = bindings[i].call(self, element); - if (isElement(value)) - value = ''; - else if (isObject(value)) - value = toJson(value, prettyPrintJson); - parts.push(value); + bindTemplateCache[template] = fn = function(scope, element, prettyPrintJson) { + var parts = [], + hadOwnElement = scope.hasOwnProperty('$element'), + oldElement = scope.$element; + + // TODO(misko): get rid of $element + scope.$element = element; + try { + for (var i = 0; i < bindings.length; i++) { + var value = bindings[i](scope, element); + if (isElement(value)) + value = ''; + else if (isObject(value)) + value = toJson(value, prettyPrintJson); + parts.push(value); + } + return parts.join(''); + } finally { + if (hadOwnElement) { + scope.$element = oldElement; + } else { + delete scope.$element; + } } - self.$element = oldElement; - return parts.join(''); }; } return fn; @@ -372,13 +398,13 @@ angularDirective("ng:bind-template", function(expression, element){ var templateFn = compileBindTemplate(expression); return function(element) { var lastValue; - this.$onEval(function() { - var value = templateFn.call(this, element, true); + this.$observe(function(scope) { + var value = templateFn(scope, element, true); if (value != lastValue) { element.text(value); lastValue = value; } - }, element); + }); }; }); @@ -446,10 +472,10 @@ var REMOVE_ATTRIBUTES = { angularDirective("ng:bind-attr", function(expression){ return function(element){ var lastValue = {}; - this.$onEval(function(){ - var values = this.$eval(expression); + this.$observe(function(scope){ + var values = scope.$eval(expression); for(var key in values) { - var value = compileBindTemplate(values[key]).call(this, element), + var value = compileBindTemplate(values[key])(scope, element), specialName = REMOVE_ATTRIBUTES[lowercase(key)]; if (lastValue[key] !== value) { lastValue[key] = value; @@ -467,7 +493,7 @@ angularDirective("ng:bind-attr", function(expression){ } } } - }, element); + }); }; }); @@ -510,14 +536,13 @@ angularDirective("ng:bind-attr", function(expression){ * TODO: maybe we should consider allowing users to control event propagation in the future. */ angularDirective("ng:click", function(expression, element){ - return annotate('$updateView', function($updateView, element){ + return function(element){ var self = this; element.bind('click', function(event){ - self.$tryEval(expression, element); - $updateView(); + self.$apply(expression); event.stopPropagation(); }); - }); + }; }); @@ -555,28 +580,27 @@ angularDirective("ng:click", function(expression, element){ </doc:example> */ angularDirective("ng:submit", function(expression, element) { - return annotate('$updateView', function($updateView, element) { + return function(element) { var self = this; element.bind('submit', function(event) { - self.$tryEval(expression, element); - $updateView(); + self.$apply(expression); event.preventDefault(); }); - }); + }; }); function ngClass(selector) { - return function(expression, element){ + return function(expression, element) { var existing = element[0].className + ' '; - return function(element){ - this.$onEval(function(){ - if (selector(this.$index)) { - var value = this.$eval(expression); + return function(element) { + this.$observe(function(scope) { + if (selector(scope.$index)) { + var value = scope.$eval(expression); if (isArray(value)) value = value.join(' '); element[0].className = trim(existing + value); } - }, element); + }); }; }; } @@ -732,9 +756,9 @@ angularDirective("ng:class-even", ngClass(function(i){return i % 2 === 1;})); */ angularDirective("ng:show", function(expression, element){ return function(element){ - this.$onEval(function(){ - toBoolean(this.$eval(expression)) ? element.show() : element.hide(); - }, element); + this.$observe(expression, function(scope, value){ + toBoolean(value) ? element.show() : element.hide(); + }); }; }); @@ -773,9 +797,9 @@ angularDirective("ng:show", function(expression, element){ */ angularDirective("ng:hide", function(expression, element){ return function(element){ - this.$onEval(function(){ - toBoolean(this.$eval(expression)) ? element.hide() : element.show(); - }, element); + this.$observe(expression, function(scope, value){ + toBoolean(value) ? element.hide() : element.show(); + }); }; }); @@ -815,8 +839,8 @@ angularDirective("ng:hide", function(expression, element){ angularDirective("ng:style", function(expression, element){ return function(element){ var resetStyle = getStyle(element); - this.$onEval(function(){ - var style = this.$eval(expression) || {}, key, mergedStyle = {}; + this.$observe(function(scope){ + var style = scope.$eval(expression) || {}, key, mergedStyle = {}; for(key in style) { if (resetStyle[key] === undefined) resetStyle[key] = ''; mergedStyle[key] = style[key]; @@ -825,7 +849,7 @@ angularDirective("ng:style", function(expression, element){ mergedStyle[key] = mergedStyle[key] || resetStyle[key]; } element.css(mergedStyle); - }, element); + }); }; }); |
