diff --git a/lib/directive/module.dart b/lib/directive/module.dart
index 842f9001f..670933add 100644
--- a/lib/directive/module.dart
+++ b/lib/directive/module.dart
@@ -5,7 +5,6 @@
* This package is imported for you as part of [angular.dart](#angular/angular),
* and lists all of the basic directives that are part of Angular.
*
-*
*/
library angular.directive;
@@ -69,8 +68,8 @@ class NgDirectiveModule extends Module {
value(ContentEditableDirective, null);
value(NgModel, null);
value(NgValue, new NgValue(null));
- value(NgTrueValue, new NgTrueValue(null));
- value(NgFalseValue, new NgFalseValue(null));
+ value(NgTrueValue, new NgTrueValue());
+ value(NgFalseValue, new NgFalseValue());
value(NgSwitchDirective, null);
value(NgSwitchWhenDirective, null);
value(NgSwitchDefaultDirective, null);
diff --git a/lib/directive/ng_model.dart b/lib/directive/ng_model.dart
index 38d054500..5f7deb4fe 100644
--- a/lib/directive/ng_model.dart
+++ b/lib/directive/ng_model.dart
@@ -265,17 +265,32 @@ class NgModel extends NgControl implements NgAttachAware {
/**
* Usage:
*
- *
+ *
*
- * This creates a two way databinding between the boolean expression specified
- * in ng-model and the checkbox input element in the DOM. If the ng-model value
- * is falsy (i.e. one of `false`, `null`, and `0`), then the checkbox is
- * unchecked. Otherwise, it is checked. Likewise, when the checkbox is checked,
- * the model value is set to true. When unchecked, it is set to false.
+ * This creates a two way databinding between the `ng-model` expression
+ * and the checkbox input element state.
+ *
+ * If the optional `ng-true-value` is absent then: if the model expression
+ * evaluates to true or to a nonzero [num], then the checkbox is checked;
+ * otherwise, it is unchecked.
+ *
+ * If `ng-true-value="t_expr"` is present, then: if the model expression
+ * evaluates to the same value as `t_expr` then the checkbox is checked;
+ * otherwise, it is unchecked.
+ *
+ * When the checkbox is checked, the model is set to the value of `t_expr` if
+ * present, true otherwise. When unchecked, it is set to the value of
+ * `f_expr` if present, false otherwise.
+ *
+ * Also see [NgTrueValue] and [NgFalseValue].
*/
@NgDirective(selector: 'input[type=checkbox][ng-model]')
class InputCheckboxDirective {
- final dom.InputElement inputElement;
+ final dom.CheckboxInputElement inputElement;
final NgModel ngModel;
final NgTrueValue ngTrueValue;
final NgFalseValue ngFalseValue;
@@ -285,14 +300,13 @@ class InputCheckboxDirective {
this.scope, this.ngTrueValue, this.ngFalseValue) {
ngModel.render = (value) {
scope.rootScope.domWrite(() {
- inputElement.checked = ngTrueValue.isValue(inputElement, value);
+ inputElement.checked = ngTrueValue.isValue(value);
});
};
inputElement
- ..onChange.listen((value) {
+ ..onChange.listen((_) {
ngModel.viewValue = inputElement.checked
- ? ngTrueValue.readValue(inputElement)
- : ngFalseValue.readValue(inputElement);
+ ? ngTrueValue.value : ngFalseValue.value;
})
..onBlur.listen((e) {
ngModel.markAsTouched();
@@ -473,44 +487,45 @@ class NgValue {
}
/**
- * `ng-true-value` allows you to select any expression to be set to
- * `ng-model` when checkbox is selected on ``.
+ * Usage:
+ *
+ *
+ *
+ * The initial value of the expression bound to this directive is assigned to
+ * the model when the input is checked. Note that the expression can be of any
+ * type, not just [String]. Also see [InputCheckboxDirective], [NgFalseValue].
*/
-@NgDirective(selector: '[ng-true-value]')
+@NgDirective(selector: 'input[type=checkbox][ng-model][ng-true-value]')
class NgTrueValue {
final dom.Element element;
@NgOneWay('ng-true-value')
- var value;
-
- NgTrueValue(this.element);
+ var value = true;
- readValue(dom.Element element) {
- assert(this.element == null || element == this.element);
- return this.element == null ? true : value;
- }
+ NgTrueValue([this.element]);
- bool isValue(dom.Element element, value) {
- assert(this.element == null || element == this.element);
- return this.element == null ? toBool(value) : value == this.value;
- }
+ bool isValue(val) => element == null ? toBool(val) : val == value;
}
/**
- * `ng-false-value` allows you to select any expression to be set to
- * `ng-model` when checkbox is deselected `.
+ * Usage:
+ *
+ *
+ *
+ * The initial value of the expression bound to this directive is assigned to
+ * the model when the input is unchecked. Note that the expression can be of any
+ * type, not just [String]. Also see [InputCheckboxDirective], [NgTrueValue].
*/
-@NgDirective(selector: '[ng-false-value]')
+@NgDirective(selector: 'input[type=checkbox][ng-model][ng-false-value]')
class NgFalseValue {
final dom.Element element;
@NgOneWay('ng-false-value')
- var value;
-
- NgFalseValue(this.element);
+ var value = false;
- readValue(dom.Element element) {
- assert(this.element == null || element == this.element);
- return this.element == null ? false : value;
- }
+ NgFalseValue([this.element]);
}
/**
diff --git a/test/directive/ng_model_spec.dart b/test/directive/ng_model_spec.dart
index e16060dc8..d3d069b85 100644
--- a/test/directive/ng_model_spec.dart
+++ b/test/directive/ng_model_spec.dart
@@ -631,7 +631,6 @@ void main() {
expect(model.dirty).toEqual(true);
});
-
it('should update input value from model using ng-true-value/false', (Scope scope) {
var element = _.compile('');
@@ -654,7 +653,6 @@ void main() {
expect(scope.context['model']).toBe(0);
});
-
it('should allow non boolean values like null, 0, 1', (Scope scope) {
var element = _.compile('');
@@ -674,7 +672,6 @@ void main() {
expect(element.checked).toBe(false);
});
-
it('should update model from the input value', (Scope scope) {
var element = _.compile('');
@@ -687,6 +684,23 @@ void main() {
expect(scope.context['model']).toBe(false);
});
+ it('should update model from the input using ng-true-value/false', (Scope scope) {
+ var element = _.compile('');
+ scope.apply(() {
+ scope.context['yes'] = 'yes sir!';
+ scope.context['no'] = 'no, sorry';
+ });
+
+ element.checked = true;
+ _.triggerEvent(element, 'change');
+ expect(scope.context['model']).toEqual('yes sir!');
+
+ element.checked = false;
+ _.triggerEvent(element, 'change');
+ expect(scope.context['model']).toEqual('no, sorry');
+ });
+
it('should only render the input value upon the next digest', (Scope scope) {
_.compile('');
Probe probe = _.rootScope.context['p'];