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

Commit

Permalink
feat(forms): provide support for controls and state flags
Browse files Browse the repository at this point in the history
  • Loading branch information
matsko authored and mhevery committed Jan 24, 2014
1 parent dd02a52 commit d1d8638
Show file tree
Hide file tree
Showing 5 changed files with 388 additions and 38 deletions.
2 changes: 1 addition & 1 deletion lib/directive/module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@ class NgDirectiveModule extends Module {
value(NgStyleDirective, null);
value(NgNonBindableDirective, null);
value(NgTemplateDirective, null);
value(NgForm, null);
value(NgForm, new NgNullForm());
}
}
120 changes: 117 additions & 3 deletions lib/directive/ng_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,129 @@ part of angular.directive;
@NgDirective(
selector: 'form',
visibility: NgDirective.CHILDREN_VISIBILITY)
class NgForm {
dom.Element _element;
Scope _scope;
@NgDirective(
selector: '.ng-form',
visibility: NgDirective.CHILDREN_VISIBILITY)
@NgDirective(
selector: '[ng-form]',
visibility: NgDirective.CHILDREN_VISIBILITY)
class NgForm extends NgDetachAware {
static const String NG_VALID_CLASS = "ng-valid";
static const String NG_INVALID_CLASS = "ng-invalid";
static const String NG_PRISTINE_CLASS = "ng-pristine";
static const String NG_DIRTY_CLASS = "ng-dirty";

final dom.Element _element;
final Scope _scope;

String _name;

bool _dirty;
bool _pristine;
bool _valid;
bool _invalid;

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

NgForm(this._scope, this._element) {
if(!this._element.attributes.containsKey('action')) {
this._element.onSubmit.listen((event) {
event.preventDefault();
});
}

this.pristine = true;
}

detach() {
for (int i = _controls.length - 1; i >= 0; --i) {
removeControl(_controls[i]);
}
}

@NgAttr('name')
get name => _name;
set name(name) {
_name = name;
_scope[name] = this;
}

get pristine => _pristine;
set pristine(value) {
_pristine = true;
_dirty = false;

_element.classes.remove(NG_DIRTY_CLASS);
_element.classes.add(NG_PRISTINE_CLASS);
}

get dirty => _dirty;
set dirty(value) {
_dirty = true;
_pristine = false;

_element.classes.remove(NG_PRISTINE_CLASS);
_element.classes.add(NG_DIRTY_CLASS);
}

get valid => _valid;
set valid(value) {
_invalid = false;
_valid = true;

_element.classes.remove(NG_INVALID_CLASS);
_element.classes.add(NG_VALID_CLASS);
}

get invalid => _invalid;
set invalid(value) {
_valid = false;
_invalid = true;

_element.classes.remove(NG_VALID_CLASS);
_element.classes.add(NG_INVALID_CLASS);
}

operator[](name) {
return _controlByName[name];
}

addControl(NgModel control) {
_controls.add(control);
if(control.name != null) {
_controlByName[control.name] = control;
}
}

removeControl(NgModel control) {
_controls.remove(control);
if(control.name != null) {
_controlByName.remove(control.name);
}
}
}

class NgNullForm implements NgForm {
NgNullForm() {}
operator[](name) {}
operator []=(String name, value) {}
addControl(control) {}
removeControl(control) {}
setValidity(control, String errorType, bool isValid) {}

get name => null;
set name(name) {}

get pristine => null;
set pristine(value) {}

get dirty => null;
set dirty(value) {}

get valid => null;
set valid(value) {}

get invalid => null;
set invalid(value) {}
}
61 changes: 58 additions & 3 deletions lib/directive/ng_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,41 @@ part of angular.directive;
* (to be implemented)
*/
@NgDirective(
selector: '[ng-model]',
map: const {'ng-model': '&model'})
selector: '[ng-model]')
class NgModel {
final NgForm _form;
final dom.Element _element;
final Scope _scope;

Getter getter = ([_]) => null;
Setter setter = (_, [__]) => null;

String _exp;
String _name;

bool _dirty;
bool _pristine;
bool _valid;
bool _invalid;

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]) {

This comment has been minimized.

Copy link
@zoechi

zoechi Jan 30, 2014

Contributor

May I ask what purpose optional parameters in the constructor fulfill for injected types?
I haven't found information how DI handles them.

This comment has been minimized.

Copy link
@mhevery

mhevery Jan 31, 2014

Contributor

@matsko That is an excellent question. Why are they optional? That is weird with DI.

_exp = 'ng-model=${attrs["ng-model"]}';
watchCollection = false;

_form.addControl(this);
pristine = true;
}

@NgAttr('name')
get name => _name;
set name(value) {
_name = value;
_form.addControl(this);
}

get watchCollection => _watchCollection;
Expand All @@ -43,6 +60,7 @@ class NgModel {
}
}

@NgCallback('ng-model')
set model(BoundExpression boundExpression) {
getter = boundExpression;
setter = boundExpression.assign;
Expand All @@ -55,6 +73,43 @@ class NgModel {

get modelValue => getter();
set modelValue(value) => setter(value);

get pristine => _pristine;
set pristine(value) {
_pristine = true;
_dirty = false;
_element.classes.remove(NgForm.NG_DIRTY_CLASS);
_element.classes.add(NgForm.NG_PRISTINE_CLASS);
}

get dirty => _dirty;
set dirty(value) {
_dirty = true;
_pristine = false;
_element.classes.remove(NgForm.NG_PRISTINE_CLASS);
_element.classes.add(NgForm.NG_DIRTY_CLASS);
}

get valid => _valid;
set valid(value) {
_invalid = false;
_valid = true;
_element.classes.remove(NgForm.NG_INVALID_CLASS);
_element.classes.add(NgForm.NG_VALID_CLASS);
}

get invalid => _invalid;
set invalid(value) {
_valid = false;
_invalid = true;
_element.classes.remove(NgForm.NG_VALID_CLASS);
_element.classes.add(NgForm.NG_INVALID_CLASS);
}


destroy() {
_form.removeControl(this);
}
}

/**
Expand Down
Loading

0 comments on commit d1d8638

Please sign in to comment.