Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Unified Diff: third_party/pkg/angular/lib/directive/ng_model.dart

Issue 148453003: Updating Angular version (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/pkg/angular/lib/directive/ng_model.dart
diff --git a/third_party/pkg/angular/lib/directive/ng_model.dart b/third_party/pkg/angular/lib/directive/ng_model.dart
index 2028851afd45e45c456a466f7cb33a63194c6bb4..df4612c23c15fc90a56d4f99dee6808ca7566c5f 100644
--- a/third_party/pkg/angular/lib/directive/ng_model.dart
+++ b/third_party/pkg/angular/lib/directive/ng_model.dart
@@ -7,28 +7,45 @@ part of angular.directive;
* provide the rendering and listening capabilities. The directive itself
* knows how to convert the view-value into model-value and vice versa by
* allowing others to register converters (To be implemented). It also
- * knwos how to (in)validate the model and the form in which it is declared
+ * knows how to (in)validate the model and the form in which it is declared
* (to be implemented)
*/
@NgDirective(
- selector: '[ng-model]',
- map: const {'ng-model': '&model'})
-class NgModel {
+ selector: '[ng-model]')
+class NgModel extends NgControl {
+ final NgForm _form;
+ final dom.Element _element;
final Scope _scope;
Getter getter = ([_]) => null;
Setter setter = (_, [__]) => null;
+
String _exp;
+ String _name;
+ final List<_NgModelValidator> _validators = new List<_NgModelValidator>();
+ final Map<String, bool> currentErrors = new Map<String, bool>();
Function _removeWatch = () => null;
bool _watchCollection;
Function render = (value) => null;
- NgModel(this._scope, NodeAttrs attrs) {
+ NgModel(this._scope, NodeAttrs attrs, [dom.Element this._element, NgForm this._form]) {
_exp = 'ng-model=${attrs["ng-model"]}';
watchCollection = false;
+
+ _form.addControl(this);
+ pristine = true;
+ }
+
+ get element => _element;
+
+ @NgAttr('name')
+ get name => _name;
+ set name(value) {
+ _name = value;
+ _form.addControl(this);
}
get watchCollection => _watchCollection;
@@ -43,6 +60,7 @@ class NgModel {
}
}
+ @NgCallback('ng-model')
set model(BoundExpression boundExpression) {
getter = boundExpression;
setter = boundExpression.assign;
@@ -55,6 +73,71 @@ class NgModel {
get modelValue => getter();
set modelValue(value) => setter(value);
+
+ get validators => _validators;
+
+ /**
+ * Executes a validation on the form against each of the validation present on the model.
+ */
+ validate() {
+ if(validators.length > 0) {
+ validators.forEach((validator) {
+ setValidity(validator.name, validator.isValid());
+ });
+ } else {
+ valid = true;
+ }
+ }
+
+ /**
+ * Sets the validity status of the given errorType on the model. Depending on if
+ * valid or invalid, the matching CSS classes will be added/removed on the input
+ * element associated with the model. If any errors exist on the model then invalid
+ * will be set to true otherwise valid will be set to true.
+ *
+ * * [errorType] - The name of the error (e.g. required, url, number, etc...).
+ * * [isValid] - Whether or not the given error is valid or not (false would mean the error is real).
+ */
+ setValidity(String errorType, bool isValid) {
+ if(isValid) {
+ if(currentErrors.containsKey(errorType)) {
+ currentErrors.remove(errorType);
+ }
+ if(valid != true && currentErrors.isEmpty) {
+ valid = true;
+ }
+ } else if(!currentErrors.containsKey(errorType)) {
+ currentErrors[errorType] = true;
+ invalid = true;
+ }
+
+ if(_form != null) {
+ _form.setValidity(this, errorType, isValid);
+ }
+ }
+
+ /**
+ * Registers a validator into the model to consider when running validate().
+ */
+ addValidator(_NgModelValidator v) {
+ validators.add(v);
+ validate();
+ }
+
+ /**
+ * De-registers a validator from the model.
+ */
+ removeValidator(_NgModelValidator v) {
+ validators.remove(v);
+ validate();
+ }
+
+ /**
+ * Removes the model from the control/form.
+ */
+ destroy() {
+ _form.removeControl(this);
+ }
}
/**
@@ -86,16 +169,35 @@ class InputCheckboxDirective {
}
}
-
-abstract class _InputTextlikeDirective {
+/**
+ * Usage:
+ *
+ * <input type="text|number|url|password|email" ng-model="myModel">
+ * <textarea ng-model="myModel"></textarea>
+ *
+ * This creates a two-way binding between any string-based input element
+ * (both <input> and <textarea>) so long as the ng-model attribute is
+ * present on the input element. Whenever the value of the input element
+ * changes then the matching model property on the scope will be updated
+ * as well as the other way around (when the scope property is updated).
+ *
+ */
+@NgDirective(selector: 'textarea[ng-model]')
+@NgDirective(selector: 'input[type=text][ng-model]')
+@NgDirective(selector: 'input[type=password][ng-model]')
+@NgDirective(selector: 'input[type=url][ng-model]')
+@NgDirective(selector: 'input[type=email][ng-model]')
+@NgDirective(selector: 'input[type=number][ng-model]')
+class InputTextLikeDirective {
dom.Element inputElement;
NgModel ngModel;
Scope scope;
+ String _inputType;
get typedValue => (inputElement as dynamic).value;
- set typedValue(String value) => (inputElement as dynamic).value = (value == null) ? '' : value;
+ set typedValue(value) => (inputElement as dynamic).value = (value == null) ? '' : value.toString();
- _InputTextlikeDirective(dom.Element this.inputElement, this.ngModel, this.scope) {
+ InputTextLikeDirective(dom.Element this.inputElement, NgModel this.ngModel, Scope this.scope) {
ngModel.render = (value) {
if (value == null) value = '';
@@ -112,6 +214,7 @@ abstract class _InputTextlikeDirective {
}
processValue() {
+ ngModel.validate();
var value = typedValue;
if (value != ngModel.viewValue) {
scope.$apply(() => ngModel.viewValue = value);
@@ -119,145 +222,6 @@ abstract class _InputTextlikeDirective {
}
}
-/**
- * Usage:
- *
- * <input type="text" ng-model="name">
- *
- * This creates a two way databinding between the expression specified in
- * ng-model and the text input element in the DOM.  If the ng-model value is
- * `null`, it is treated as equivalent to the empty string for rendering
- * purposes.
- */
-@NgDirective(selector: 'input[type=text][ng-model]')
-class InputTextDirective extends _InputTextlikeDirective {
- InputTextDirective(dom.Element inputElement, NgModel ngModel, Scope scope):
- super(inputElement, ngModel, scope);
-
-}
-
-/**
- * Usage:
- *
- * <input type="password" ng-model="name">
- *
- * This creates a two way databinding between the expression specified in
- * ng-model and the password input element in the DOM.  If the ng-model value is
- * `null`, it is treated as equivalent to the empty string for rendering
- * purposes.
- */
-@NgDirective(selector: 'input[type=password][ng-model]')
-class InputPasswordDirective extends _InputTextlikeDirective {
- InputPasswordDirective(dom.Element inputElement, NgModel ngModel, Scope scope):
- super(inputElement, ngModel, scope);
-}
-
-/**
- * Usage:
- *
- * <textarea ng-model="text">
- *
- * This creates a two way databinding between the expression specified in
- * ng-model and the textarea element in the DOM.  If the ng-model value is
- * `null`, it is treated as equivalent to the empty string for rendering
- * purposes.
- */
-@NgDirective(selector: 'textarea[ng-model]')
-class TextAreaDirective extends _InputTextlikeDirective {
- TextAreaDirective(dom.Element inputElement, NgModel ngModel, Scope scope):
- super(inputElement, ngModel, scope);
-}
-
-/**
- * Usage:
- *
- * <input type="number" ng-model="name">
- *
- * This creates a two way databinding between the expression specified in
- * ng-model and the number input element in the DOM.  If the ng-model value is
- * `null` or `NaN`, the DOM element is not updated. If the value in the DOM
- * element is an invalid number, then the expression specified by the `ng-model`
- * is set to null.,
- */
-@NgDirective(selector: 'input[type=number][ng-model]')
-class InputNumberDirective extends _InputTextlikeDirective {
- InputNumberDirective(dom.Element inputElement, NgModel ngModel, Scope scope):
- super(inputElement, ngModel, scope);
-
- get typedValue => (inputElement as dom.InputElement).valueAsNumber;
-
- set typedValue(var value) {
- if (value != null && value is num) {
- num number = value as num;
- if (!value.isNaN) {
- (inputElement as dom.InputElement).valueAsNumber = value;
- }
- }
- }
-}
-
-/**
- * Usage:
- *
- * <input type="email" ng-model="emailAddress">
- *
- * This creates a two way databinding between the expression specified in
- * ng-model and the email input element in the DOM.  If the ng-model value is
- * `null`, the DOM element is not updated. If the value in the DOM element is
- * an invalid e-mail address, then the expression specified by the `ng-model` is
- * set to null.,
- */
-@NgDirective(selector: 'input[type=email][ng-model]')
-class InputEmailDirective extends _InputTextlikeDirective {
- static final EMAIL_REGEXP = new RegExp(
- r'^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}$');
- InputEmailDirective(dom.Element inputElement, NgModel ngModel, Scope scope):
- super(inputElement, ngModel, scope);
-
- String get typedValue {
- String value = (inputElement as dom.InputElement).value;
- return EMAIL_REGEXP.hasMatch(value) ? value : null;
- }
-
- set typedValue(String value) {
- if (value != null && EMAIL_REGEXP.hasMatch(value)) {
- (inputElement as dom.InputElement).value = value;
- }
- }
-}
-
-
-/**
- * Usage:
- *
- * <input type="url" ng-model="website">
- *
- * This creates a two way databinding between the expression specified in
- * ng-model and the `url` input element in the DOM.  If the ng-model value is
- * `null`, the DOM element is not updated. If the value in the DOM element is
- * an invalid URL, then the expression specified by the `ng-model` is set to
- * null.,
- */
-@NgDirective(selector: 'input[type=url][ng-model]')
-class InputUrlDirective extends _InputTextlikeDirective {
- static final URL_REGEXP = new RegExp(
- r'^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?' +
- r'(\/|\/([\w#!:.?+=&%@!\-\/]))?$');
- InputUrlDirective(dom.Element inputElement, NgModel ngModel, Scope scope):
- super(inputElement, ngModel, scope);
-
- String get typedValue {
- String value = (inputElement as dom.InputElement).value;
- return URL_REGEXP.hasMatch(value) ? value : null;
- }
-
- set typedValue(String value) {
- if (value != null && URL_REGEXP.hasMatch(value)) {
- (inputElement as dom.InputElement).value = value;
- }
- }
-}
-
class _UidCounter {
static final int CHAR_0 = "0".codeUnitAt(0);
static final int CHAR_9 = "9".codeUnitAt(0);
@@ -325,3 +289,23 @@ class InputRadioDirective {
});
}
}
+
+/**
+ * Usage (span could be replaced with any element which supports text content, such as `p`):
+ *
+ * <span contenteditable= ng-model="name">
+ *
+ * This creates a two way databinding between the expression specified in
+ * ng-model and the html element in the DOM.  If the ng-model value is
+ * `null`, it is treated as equivalent to the empty string for rendering
+ * purposes.
+ */
+@NgDirective(selector: '[contenteditable][ng-model]')
+class ContentEditableDirective extends InputTextLikeDirective {
+ ContentEditableDirective(dom.Element inputElement, NgModel ngModel, Scope scope):
+ super(inputElement, ngModel, scope);
+
+ // The implementation is identical to InputTextLikeDirective but use innerHtml instead of value
+ get typedValue => (inputElement as dynamic).innerHtml;
+ set typedValue(String value) => (inputElement as dynamic).innerHtml = (value == null) ? '' : value;
+}
« no previous file with comments | « third_party/pkg/angular/lib/directive/ng_form.dart ('k') | third_party/pkg/angular/lib/directive/ng_model_validators.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698