diff --git a/example/web/hello_world.dart b/example/web/hello_world.dart
index ab8953f72..871164ace 100644
--- a/example/web/hello_world.dart
+++ b/example/web/hello_world.dart
@@ -6,6 +6,7 @@ import 'package:angular/application_factory.dart';
publishAs: 'ctrl')
class HelloWorld {
String name = "world";
+ String color = "#aaaaaa";
}
main() {
diff --git a/example/web/hello_world.html b/example/web/hello_world.html
index 705607d48..addcb05b2 100644
--- a/example/web/hello_world.html
+++ b/example/web/hello_world.html
@@ -5,8 +5,9 @@
-Hello {{ctrl.name}}!
-name:
+Hello {{ctrl.name}}!
+Name:
+Color:
diff --git a/lib/directive/module.dart b/lib/directive/module.dart
index c5b307983..f82b68561 100644
--- a/lib/directive/module.dart
+++ b/lib/directive/module.dart
@@ -118,5 +118,6 @@ class DirectiveModule extends Module {
bind(NgModelPatternValidator, toValue: null);
bind(NgModelMinLengthValidator, toValue: null);
bind(NgModelMaxLengthValidator, toValue: null);
+ bind(NgModelColorValidator, toValue: null);
}
}
diff --git a/lib/directive/ng_model.dart b/lib/directive/ng_model.dart
index 1ca0b9c85..06ef8018c 100644
--- a/lib/directive/ng_model.dart
+++ b/lib/directive/ng_model.dart
@@ -332,7 +332,7 @@ class InputCheckbox {
*
* **Usage**
*
- *
+ *
*
*
* When the `ng-model` attribute is present on the input element,
@@ -348,6 +348,7 @@ class InputCheckbox {
@Decorator(selector: 'input[type=email][ng-model]')
@Decorator(selector: 'input[type=search][ng-model]')
@Decorator(selector: 'input[type=tel][ng-model]')
+@Decorator(selector: 'input[type=color][ng-model]')
class InputTextLike {
final dom.Element inputElement;
final NgModel ngModel;
@@ -707,7 +708,7 @@ class NgValue {
@NgOneWay('ng-value')
void set value(val) {
- this._value = val;
+ _value = val;
}
dynamic get value => _value == null ? (element as dynamic).value : _value;
}
diff --git a/lib/directive/ng_model_validators.dart b/lib/directive/ng_model_validators.dart
index b0537399f..ed051ab3f 100644
--- a/lib/directive/ng_model_validators.dart
+++ b/lib/directive/ng_model_validators.dart
@@ -68,6 +68,22 @@ class NgModelUrlValidator implements NgValidator {
modelValue == null || modelValue.isEmpty || URL_REGEXP.hasMatch(modelValue);
}
+/**
+ * Validates the model to see if its contents match a valid color pattern.
+ */
+@Decorator(selector: 'input[type=color][ng-model]')
+class NgModelColorValidator implements NgValidator {
+ static final COLOR_REGEXP = new RegExp(r'^#[0-9a-f]{6}$', caseSensitive: false);
+ final String name = 'ng-color';
+
+ NgModelColorValidator(NgModel ngModel) {
+ ngModel.addValidator(this);
+ }
+
+ bool isValid(modelValue) =>
+ modelValue == null || modelValue.isEmpty || COLOR_REGEXP.hasMatch(modelValue);
+}
+
/**
* Validates the model to see if its contents match a valid email pattern.
*/
diff --git a/test/angular_spec.dart b/test/angular_spec.dart
index b601b08da..6090fe66f 100644
--- a/test/angular_spec.dart
+++ b/test/angular_spec.dart
@@ -187,6 +187,7 @@ main() {
"angular.directive.NgInclude",
"angular.directive.NgModel",
"angular.directive.NgModelOptions",
+ "angular.directive.NgModelColorValidator",
"angular.directive.NgModelConverter",
"angular.directive.NgModelEmailValidator",
"angular.directive.NgModelMaxLengthValidator",
diff --git a/test/directive/ng_model_spec.dart b/test/directive/ng_model_spec.dart
index 76e485919..d42f7237e 100644
--- a/test/directive/ng_model_spec.dart
+++ b/test/directive/ng_model_spec.dart
@@ -1101,6 +1101,60 @@ void main() {
});
});
+ describe('type="color"', () {
+ it('should update input value from model', () {
+ _.compile('');
+ _.rootScope.apply();
+
+ expect((_.rootElement as dom.InputElement).value).toEqual('#000000');
+
+ _.rootScope.apply('model = "#123456"');
+ expect((_.rootElement as dom.InputElement).value).toEqual('#123456');
+ });
+
+ it('should render as #000000 on default and when a null value is present', () {
+ _.compile('');
+ _.rootScope.apply();
+
+ expect((_.rootElement as dom.InputElement).value).toEqual('#000000');
+
+ _.rootScope.apply('model = null');
+ expect((_.rootElement as dom.InputElement).value).toEqual('#000000');
+ });
+
+ it('should update model from the input value', () {
+ _.compile('');
+ Probe probe = _.rootScope.context['p'];
+ var ngModel = probe.directive(NgModel);
+ InputElement inputElement = probe.element;
+
+ inputElement.value = '#000000';
+ _.triggerEvent(inputElement, 'change');
+ expect(_.rootScope.context['model']).toEqual('#000000');
+
+ inputElement.value = '#ffffff';
+ var input = probe.directive(InputTextLike);
+ input.processValue();
+ expect(_.rootScope.context['model']).toEqual('#ffffff');
+ });
+
+ it('should only render the input value upon the next digest', (Scope scope) {
+ _.compile('');
+ Probe probe = _.rootScope.context['p'];
+ var ngModel = probe.directive(NgModel);
+ InputElement inputElement = probe.element;
+
+ ngModel.render('#aabbcc');
+ scope.context['model'] = '#aabbcc';
+
+ expect(inputElement.value).not.toEqual('#aabbcc');
+
+ scope.apply();
+
+ expect(inputElement.value).toEqual('#aabbcc');
+ });
+ });
+
describe('contenteditable', () {
it('should update content from model', () {
_.compile('');
diff --git a/test/directive/ng_model_validators_spec.dart b/test/directive/ng_model_validators_spec.dart
index 3aa9d54ee..93fbeede6 100644
--- a/test/directive/ng_model_validators_spec.dart
+++ b/test/directive/ng_model_validators_spec.dart
@@ -111,6 +111,31 @@ void main() {
});
});
+ describe('[type="color"]', () {
+ it('should validate the input field given a valid or invalid color', (RootScope scope) {
+ _.compile('');
+ Probe probe = _.rootScope.context['i'];
+ var model = probe.directive(NgModel);
+
+ expect(model.valid).toEqual(true);
+ expect(model.invalid).toEqual(false);
+
+ _.rootScope.apply(() {
+ _.rootScope.context['val'] = 'red';
+ });
+
+ expect(model.valid).toEqual(false);
+ expect(model.invalid).toEqual(true);
+
+ _.rootScope.apply(() {
+ _.rootScope.context['val'] = '#ff0000';
+ });
+
+ expect(model.valid).toEqual(true);
+ expect(model.invalid).toEqual(false);
+ });
+ });
+
describe('[type="email"]', () {
it('should validate the input field given a valid or invalid email address', (RootScope scope) {
_.compile('');
@@ -627,6 +652,6 @@ void main() {
expect(model.valid).toBe(true);
});
- });
+ });
});
}