Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

Commit d51eccf

Browse files
chalinmhevery
authored andcommitted
refactor(InputCheckboxDirective): fix API doc and refactor ng-true/false-value
- Refactor `NgTrueValue` and `NgFalseValue` so that it smells good! - Refactor/clean-up InputCheckboxDirective. - Update `input[type=checkbox]` API doc to reflect AngularDart behavior. Closes #842
1 parent 0348065 commit d51eccf

File tree

3 files changed

+69
-41
lines changed

3 files changed

+69
-41
lines changed

lib/directive/module.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
* This package is imported for you as part of [angular.dart](#angular/angular),
66
* and lists all of the basic directives that are part of Angular.
77
*
8-
*
98
*/
109
library angular.directive;
1110

@@ -70,8 +69,8 @@ class NgDirectiveModule extends Module {
7069
value(ContentEditableDirective, null);
7170
value(NgModel, null);
7271
value(NgValue, new NgValue(null));
73-
value(NgTrueValue, new NgTrueValue(null));
74-
value(NgFalseValue, new NgFalseValue(null));
72+
value(NgTrueValue, new NgTrueValue());
73+
value(NgFalseValue, new NgFalseValue());
7574
value(NgSwitchDirective, null);
7675
value(NgSwitchWhenDirective, null);
7776
value(NgSwitchDefaultDirective, null);

lib/directive/ng_model.dart

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -265,17 +265,32 @@ class NgModel extends NgControl implements NgAttachAware {
265265
/**
266266
* Usage:
267267
*
268-
* <input type="checkbox" ng-model="flag">
268+
* <input type="checkbox"
269+
* ng-model="expr"
270+
* [ng-true-value="t_expr"]
271+
* [ng-false-value="f_expr"]
272+
* >
269273
*
270-
* This creates a two way databinding between the boolean expression specified
271-
* in ng-model and the checkbox input element in the DOM.  If the ng-model value
272-
* is falsy (i.e. one of `false`, `null`, and `0`), then the checkbox is
273-
* unchecked. Otherwise, it is checked.  Likewise, when the checkbox is checked,
274-
* the model value is set to true. When unchecked, it is set to false.
274+
* This creates a two way databinding between the `ng-model` expression
275+
* and the checkbox input element state.
276+
*
277+
* If the optional `ng-true-value` is absent then: if the model expression
278+
* evaluates to true or to a nonzero [num], then the checkbox is checked;
279+
* otherwise, it is unchecked.
280+
*
281+
* If `ng-true-value="t_expr"` is present, then: if the model expression
282+
* evaluates to the same value as `t_expr` then the checkbox is checked;
283+
* otherwise, it is unchecked.
284+
*
285+
* When the checkbox is checked, the model is set to the value of `t_expr` if
286+
* present, true otherwise. When unchecked, it is set to the value of
287+
* `f_expr` if present, false otherwise.
288+
*
289+
* Also see [NgTrueValue] and [NgFalseValue].
275290
*/
276291
@NgDirective(selector: 'input[type=checkbox][ng-model]')
277292
class InputCheckboxDirective {
278-
final dom.InputElement inputElement;
293+
final dom.CheckboxInputElement inputElement;
279294
final NgModel ngModel;
280295
final NgTrueValue ngTrueValue;
281296
final NgFalseValue ngFalseValue;
@@ -285,14 +300,13 @@ class InputCheckboxDirective {
285300
this.scope, this.ngTrueValue, this.ngFalseValue) {
286301
ngModel.render = (value) {
287302
scope.rootScope.domWrite(() {
288-
inputElement.checked = ngTrueValue.isValue(inputElement, value);
303+
inputElement.checked = ngTrueValue.isValue(value);
289304
});
290305
};
291306
inputElement
292-
..onChange.listen((value) {
307+
..onChange.listen((_) {
293308
ngModel.viewValue = inputElement.checked
294-
? ngTrueValue.readValue(inputElement)
295-
: ngFalseValue.readValue(inputElement);
309+
? ngTrueValue.value : ngFalseValue.value;
296310
})
297311
..onBlur.listen((e) {
298312
ngModel.markAsTouched();
@@ -473,44 +487,45 @@ class NgValue {
473487
}
474488

475489
/**
476-
* `ng-true-value` allows you to select any expression to be set to
477-
* `ng-model` when checkbox is selected on `<input type="checkbox">`.
490+
* Usage:
491+
*
492+
* <input type=checkbox
493+
* ng-model=model
494+
* [ng-true-value=expr]>
495+
*
496+
* The initial value of the expression bound to this directive is assigned to
497+
* the model when the input is checked. Note that the expression can be of any
498+
* type, not just [String]. Also see [InputCheckboxDirective], [NgFalseValue].
478499
*/
479-
@NgDirective(selector: '[ng-true-value]')
500+
@NgDirective(selector: 'input[type=checkbox][ng-model][ng-true-value]')
480501
class NgTrueValue {
481502
final dom.Element element;
482503
@NgOneWay('ng-true-value')
483-
var value;
484-
485-
NgTrueValue(this.element);
504+
var value = true;
486505

487-
readValue(dom.Element element) {
488-
assert(this.element == null || element == this.element);
489-
return this.element == null ? true : value;
490-
}
506+
NgTrueValue([this.element]);
491507

492-
bool isValue(dom.Element element, value) {
493-
assert(this.element == null || element == this.element);
494-
return this.element == null ? toBool(value) : value == this.value;
495-
}
508+
bool isValue(val) => element == null ? toBool(val) : val == value;
496509
}
497510

498511
/**
499-
* `ng-false-value` allows you to select any expression to be set to
500-
* `ng-model` when checkbox is deselected <input type="checkbox">`.
512+
* Usage:
513+
*
514+
* <input type=checkbox
515+
* ng-model=model
516+
* [ng-false-value=expr]>
517+
*
518+
* The initial value of the expression bound to this directive is assigned to
519+
* the model when the input is unchecked. Note that the expression can be of any
520+
* type, not just [String]. Also see [InputCheckboxDirective], [NgTrueValue].
501521
*/
502-
@NgDirective(selector: '[ng-false-value]')
522+
@NgDirective(selector: 'input[type=checkbox][ng-model][ng-false-value]')
503523
class NgFalseValue {
504524
final dom.Element element;
505525
@NgOneWay('ng-false-value')
506-
var value;
507-
508-
NgFalseValue(this.element);
526+
var value = false;
509527

510-
readValue(dom.Element element) {
511-
assert(this.element == null || element == this.element);
512-
return this.element == null ? false : value;
513-
}
528+
NgFalseValue([this.element]);
514529
}
515530

516531
/**

test/directive/ng_model_spec.dart

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,6 @@ void main() {
631631
expect(model.dirty).toEqual(true);
632632
});
633633

634-
635634
it('should update input value from model using ng-true-value/false', (Scope scope) {
636635
var element = _.compile('<input type="checkbox" ng-model="model" ng-true-value="1" ng-false-value="0">');
637636

@@ -654,7 +653,6 @@ void main() {
654653
expect(scope.context['model']).toBe(0);
655654
});
656655

657-
658656
it('should allow non boolean values like null, 0, 1', (Scope scope) {
659657
var element = _.compile('<input type="checkbox" ng-model="model">');
660658

@@ -674,7 +672,6 @@ void main() {
674672
expect(element.checked).toBe(false);
675673
});
676674

677-
678675
it('should update model from the input value', (Scope scope) {
679676
var element = _.compile('<input type="checkbox" ng-model="model">');
680677

@@ -687,6 +684,23 @@ void main() {
687684
expect(scope.context['model']).toBe(false);
688685
});
689686

687+
it('should update model from the input using ng-true-value/false', (Scope scope) {
688+
var element = _.compile('<input type="checkbox" ng-model="model" '
689+
'ng-true-value="yes" ng-false-value="no">');
690+
scope.apply(() {
691+
scope.context['yes'] = 'yes sir!';
692+
scope.context['no'] = 'no, sorry';
693+
});
694+
695+
element.checked = true;
696+
_.triggerEvent(element, 'change');
697+
expect(scope.context['model']).toEqual('yes sir!');
698+
699+
element.checked = false;
700+
_.triggerEvent(element, 'change');
701+
expect(scope.context['model']).toEqual('no, sorry');
702+
});
703+
690704
it('should only render the input value upon the next digest', (Scope scope) {
691705
_.compile('<input type="checkbox" ng-model="model" probe="p">');
692706
Probe probe = _.rootScope.context['p'];

0 commit comments

Comments
 (0)