Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions lib/directive/ng_control.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ abstract class NgControl implements NgDetachAware {

final Map<String, List<NgControl>> errors = new Map<String, List<NgControl>>();
final List<NgControl> _controls = new List<NgControl>();
final Map<String, NgControl> _controlByName = new Map<String, NgControl>();
final Map<String, List<NgControl>> _controlByName = new Map<String, List<NgControl>>();

NgControl(Scope this._scope, dom.Element this._element, Injector injector,
NgAnimate this._animate)
Expand Down Expand Up @@ -144,7 +144,7 @@ abstract class NgControl implements NgDetachAware {
addControl(NgControl control) {
_controls.add(control);
if (control.name != null) {
_controlByName[control.name] = control;
_controlByName.putIfAbsent(control.name, () => new List<NgControl>()).add(control);
}
}

Expand All @@ -157,8 +157,12 @@ abstract class NgControl implements NgDetachAware {
*/
removeControl(NgControl control) {
_controls.remove(control);
if (control.name != null) {
_controlByName.remove(control.name);
String key = control.name;
if (key != null && _controlByName.containsKey(key)) {
_controlByName[key].remove(control);
if (_controlByName[key].isEmpty) {
_controlByName.remove(key);
}
}
}

Expand Down
50 changes: 6 additions & 44 deletions lib/directive/ng_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ part of angular.directive;
selector: '[ng-form]',
publishTypes : const <Type>[NgControl],
visibility: NgDirective.CHILDREN_VISIBILITY)
class NgForm extends NgControl implements Map<String, NgControl> {
class NgForm extends NgControl {
/**
* Instantiates a new instance of NgForm. Upon creation, the instance of the
* class will be bound to the formName property on the scope (where formName
Expand Down Expand Up @@ -54,56 +54,18 @@ class NgForm extends NgControl implements Map<String, NgControl> {
_scope.context[name] = this;
}

//FIXME: fix this reflection bug that shows up when Map is implemented
operator []=(String key, value) {
if (key == 'name') {
name = value;
} else {
_controlByName[key] = value;
}
}
get controls => _controlByName;

//FIXME: fix this reflection bug that shows up when Map is implemented
operator[](name) {
if (name == 'valid') {
return valid;
} else if (name == 'invalid') {
return invalid;
} else {
return _controlByName[name];
NgControl operator[](name) {
if (controls.containsKey(name)) {
return controls[name][0];
}
}

bool get isEmpty => false;
bool get isNotEmpty => !isEmpty;
get values => null;
get keys => null;
get length => null;
clear() => null;
remove(_) => null;
containsKey(_) => false;
containsValue(_) => false;
addAll(_) => null;
forEach(_) => null;
putIfAbsent(_, __) => null;
}

class NgNullForm extends NgNullControl implements NgForm {
NgNullForm() {}

operator[](name) {}
operator []=(String name, value) {}

bool get isEmpty => false;
bool get isNotEmpty => true;
get values => null;
get keys => null;
get length => null;
clear() => null;
remove(_) => null;
containsKey(_) => false;
containsValue(_) => false;
addAll(_) => null;
forEach(_) => null;
putIfAbsent(_, __) => null;
get controls => null;
}
62 changes: 62 additions & 0 deletions test/directive/ng_form_spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,50 @@ void main() {
expect(form.name).toEqual('myForm');
}));

it('should return the first control with the given name when accessed using map notation',
inject((Scope scope, TestBed _) {

var element = $('<form name="myForm">' +
' <input type="text" name="model" ng-model="modelOne" probe="a" />' +
' <input type="text" name="model" ng-model="modelTwo" probe="b" />' +
'</form>');

_.compile(element);
scope.apply();

NgForm form = _.rootScope.context['myForm'];
NgModel one = _.rootScope.context['a'].directive(NgModel);
NgModel two = _.rootScope.context['b'].directive(NgModel);

expect(one).not.toBe(two);
expect(form['model']).toBe(one);
expect(scope.eval("myForm['model']")).toBe(one);
}));

it('should return the all the controls with the given name', inject((Scope scope, TestBed _) {
var element = $('<form name="myForm">' +
' <input type="text" name="model" ng-model="modelOne" probe="a" />' +
' <input type="text" name="model" ng-model="modelTwo" probe="b" />' +
'</form>');

_.compile(element);
scope.apply();

NgForm form = _.rootScope.context['myForm'];
NgModel one = _.rootScope.context['a'].directive(NgModel);
NgModel two = _.rootScope.context['b'].directive(NgModel);

expect(one).not.toBe(two);

var controls = form.controls['model'];
expect(controls[0]).toBe(one);
expect(controls[1]).toBe(two);

expect(scope.eval("myForm.controls['model'][0]")).toBe(one);
expect(scope.eval("myForm.controls['model'][1]")).toBe(two);
}));


describe('pristine / dirty', () {
it('should be set to pristine by default', inject((Scope scope, TestBed _) {
var element = $('<form name="myForm"></form>');
Expand Down Expand Up @@ -462,6 +506,24 @@ void main() {
}));
});

it("should use map notation to fetch controls", inject((TestBed _) {
Scope s = _.rootScope;
s.context['name'] = 'cool';

var form = _.compile('<form name="myForm">' +
' <input type="text" ng-model="someModel" probe="i" name="name" />' +
'</form>');

NgForm formModel = s.context['myForm'];
Probe probe = s.context['i'];
var model = probe.directive(NgModel);

expect(s.eval('name')).toEqual('cool');
expect(s.eval('myForm.name')).toEqual('myForm');
expect(s.eval('myForm["name"]')).toBe(model);
expect(s.eval('myForm["name"].name')).toEqual("name");
}));

describe('regression tests: form', () {
it('should be resolvable by injector if configured by user.', () {
module((Module module) {
Expand Down