From 1a964bf56fbe3577b61609957b10d5292a70ba20 Mon Sep 17 00:00:00 2001 From: "todd.babbitt" Date: Tue, 13 Jun 2017 14:10:32 -0600 Subject: [PATCH 1/4] updated to work with reactive and template driven forms. --- source/connect-array.ts | 4 ++-- source/{connect.ts => connect-base.ts} | 26 ++++++++++++++------------ source/connect-reactive.ts | 24 ++++++++++++++++++++++++ source/connect-template.ts | 26 ++++++++++++++++++++++++++ source/index.ts | 4 +++- source/module.ts | 9 ++++++--- 6 files changed, 75 insertions(+), 18 deletions(-) rename source/{connect.ts => connect-base.ts} (91%) create mode 100644 source/connect-reactive.ts create mode 100644 source/connect-template.ts diff --git a/source/connect-array.ts b/source/connect-array.ts index de91ef0..baca880 100644 --- a/source/connect-array.ts +++ b/source/connect-array.ts @@ -39,7 +39,7 @@ import {Unsubscribe} from 'redux'; import {Subscription} from 'rxjs'; -import {Connect} from './connect'; +import {ConnectBase} from './connect-base'; import {FormStore} from './form-store'; import {State} from './state'; import {controlPath, selectValueAccessor} from './shims'; @@ -75,7 +75,7 @@ export class ConnectArray extends ControlContainer implements OnInit { @Optional() @Self() @Inject(NG_VALIDATORS) private rawValidators: any[], @Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) private rawAsyncValidators: any[], @Optional() @Self() @Inject(NG_VALUE_ACCESSOR) valueAccessors: any[], - private connection: Connect, + private connection: ConnectBase, private templateRef: TemplateRef, private viewContainerRef: ViewContainerRef, private store: FormStore, diff --git a/source/connect.ts b/source/connect-base.ts similarity index 91% rename from source/connect.ts rename to source/connect-base.ts index e3618aa..1b4f7f3 100644 --- a/source/connect.ts +++ b/source/connect-base.ts @@ -27,21 +27,15 @@ export interface ControlPair { control: AbstractControl; } -@Directive({ - selector: 'form[connect]', -}) -export class Connect { - @Input('connect') connect: () => (string | number) | Array; +export class ConnectBase { + @Input('connect') connect: () => (string | number) | Array; private stateSubscription: Unsubscribe; private formSubscription: Subscription; - - constructor( - private store: FormStore, - private form: NgForm - ) {} - + protected store: FormStore; + protected form; + public get path(): Array { const path = typeof this.connect === 'function' ? this.connect() @@ -112,7 +106,15 @@ export class Connect { } private resetState() { - const children = this.descendants([], this.form.control); + var formElement; + if (this.form.control === undefined){ + formElement = this.form; + } + else{ + formElement = this.form.control; + } + + const children = this.descendants([], formElement); children.forEach(c => { const {path, control} = c; diff --git a/source/connect-reactive.ts b/source/connect-reactive.ts new file mode 100644 index 0000000..0b4b119 --- /dev/null +++ b/source/connect-reactive.ts @@ -0,0 +1,24 @@ +import { + Directive, + Input, +} from '@angular/core'; + +import { + NgForm +} from '@angular/forms'; + +import {FormStore} from './form-store'; + +import {ConnectBase} from './connect-base'; + +// For reactive forms (without implicit NgForm) +@Directive({ selector: 'form[connect][formGroup]' }) +export class ConnectReactiveDirective extends ConnectBase { + @Input('formGroup') form; + + constructor( + protected store: FormStore + ) { + super(); + } +} diff --git a/source/connect-template.ts b/source/connect-template.ts new file mode 100644 index 0000000..4735b0b --- /dev/null +++ b/source/connect-template.ts @@ -0,0 +1,26 @@ +import { + Directive, + Input, +} from '@angular/core'; + +import { + NgForm +} from '@angular/forms'; + + +import {FormStore} from './form-store'; +import {State} from './state'; +import {ConnectBase} from './connect-base'; + + +// For template forms (with implicit NgForm) +@Directive({ selector: 'form[connect]:not([formGroup])' }) +export class ConnectTemplateDirective extends ConnectBase { + + constructor( + protected store: FormStore, + protected form: NgForm + ) { + super(); + } +} diff --git a/source/index.ts b/source/index.ts index d942e12..56b986b 100644 --- a/source/index.ts +++ b/source/index.ts @@ -3,6 +3,8 @@ export * from './form-reducer'; export * from './form-exception'; export * from './form-store'; export * from './configure'; -export * from './connect'; +export * from './connect-base'; +export * from './connect-reactive'; +export * from './connect-template'; export * from './connect-array'; export * from './module'; diff --git a/source/module.ts b/source/module.ts index b24d255..7e9739e 100644 --- a/source/module.ts +++ b/source/module.ts @@ -3,7 +3,8 @@ import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {NgRedux} from '@angular-redux/store'; -import {Connect} from './connect'; +import {ConnectReactiveDirective} from './connect-reactive'; +import {ConnectTemplateDirective} from './connect-template'; import {ConnectArray} from './connect-array'; import {FormStore} from './form-store'; @@ -17,11 +18,13 @@ export function formStoreFactory(ngRedux: NgRedux) { ReactiveFormsModule, ], declarations: [ - Connect, + ConnectTemplateDirective, + ConnectReactiveDirective, ConnectArray, ], exports: [ - Connect, + ConnectTemplateDirective, + ConnectReactiveDirective, ConnectArray, ], providers: [ From c1454a654f69827b43cfd73b4c2e21d0bf85ce92 Mon Sep 17 00:00:00 2001 From: "todd.babbitt" Date: Tue, 13 Jun 2017 14:17:10 -0600 Subject: [PATCH 2/4] added a little documentation --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index f087775..604c80c 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,10 @@ your forms elements. It builds on existing Angular functionality like and [NgControl](https://angular.io/docs/ts/latest/api/forms/index/NgControl-class.html) +This supports both [Tempalte driven forms](https://angular.io/guide/forms) and [Reactive driven forms](https://angular.io/guide/reactive-forms). + +#### Template Driven + For the simplest use-cases, the API is very straightforward. Your template would look something like this: @@ -203,6 +207,15 @@ the `path` property on our first ` + +``` + #### Troubleshooting If you are having trouble getting data-binding to work for an element of your form, From d61c0d07ea6fe42618804ce7e4a4fc779efdcb5e Mon Sep 17 00:00:00 2001 From: "todd.babbitt" Date: Thu, 22 Jun 2017 10:07:14 -0500 Subject: [PATCH 3/4] updated based on PR feedback --- README.md | 2 +- source/connect-base.ts | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 604c80c..7f7a256 100644 --- a/README.md +++ b/README.md @@ -208,7 +208,7 @@ From there, `@angular-redux/form` is able to take that path and extract the valu that element from the Redux state. #### Reactive Forms -The value in "connect" attribute is the value that will show up in the Redux store. The formGrup value is the name of hte object in your code that represents the form group. +The value in "connect" attribute is the value that will show up in the Redux store. The formGroup value is the name of the object in your code that represents the form group. ```html
diff --git a/source/connect-base.ts b/source/connect-base.ts index 1b4f7f3..27a201e 100644 --- a/source/connect-base.ts +++ b/source/connect-base.ts @@ -12,15 +12,15 @@ import { NgControl, } from '@angular/forms'; -import {Subscription} from 'rxjs'; +import { Subscription } from 'rxjs'; -import {Unsubscribe} from 'redux'; +import { Unsubscribe } from 'redux'; import 'rxjs/add/operator/debounceTime'; -import {FormException} from './form-exception'; -import {FormStore} from './form-store'; -import {State} from './state'; +import { FormException } from './form-exception'; +import { FormStore } from './form-store'; +import { State } from './state'; export interface ControlPair { path: Array; @@ -35,7 +35,7 @@ export class ConnectBase { private formSubscription: Subscription; protected store: FormStore; protected form; - + public get path(): Array { const path = typeof this.connect === 'function' ? this.connect() @@ -47,16 +47,16 @@ export class ConnectBase { return []; } if (Array.isArray(path)) { - return > path; + return >path; } case 'string': - return ( path).split(/\./g); + return (path).split(/\./g); default: // fallthrough above (no break) throw new Error(`Cannot determine path to object: ${JSON.stringify(path)}`); } } - ngOnDestroy () { + ngOnDestroy() { if (this.formSubscription) { this.formSubscription.unsubscribe(); } @@ -92,11 +92,11 @@ export class ConnectBase { } else if (formElement instanceof FormGroup) { for (const k of Object.keys(formElement.controls)) { - pairs.push({path:path.concat([k]), control: formElement.controls[k]}); + pairs.push({ path: path.concat([k]), control: formElement.controls[k] }); } } else if (formElement instanceof NgControl || formElement instanceof FormControl) { - return [{path: path, control: formElement}]; + return [{ path: path, control: formElement }]; } else { throw new Error(`Unknown type of form element: ${formElement.constructor.name}`); @@ -107,22 +107,22 @@ export class ConnectBase { private resetState() { var formElement; - if (this.form.control === undefined){ + if (this.form.control === undefined) { formElement = this.form; } - else{ - formElement = this.form.control; - } + else { + formElement = this.form.control; + } const children = this.descendants([], formElement); children.forEach(c => { - const {path, control} = c; + const { path, control } = c; const value = State.get(this.getState(), this.path.concat(c.path)); if (control.value !== value) { - const phonyControl = {path: path}; + const phonyControl = { path: path }; this.form.updateModel(phonyControl, value); } From 713664c43bc0aa5adb4ebe62a66845d1e5330412 Mon Sep 17 00:00:00 2001 From: "todd.babbitt" Date: Tue, 27 Jun 2017 08:28:13 -0600 Subject: [PATCH 4/4] updated based on PR feedback. --- source/connect-reactive.ts | 2 +- source/{connect-template.ts => connect.ts} | 2 +- source/index.ts | 2 +- source/module.ts | 12 ++++++------ 4 files changed, 9 insertions(+), 9 deletions(-) rename source/{connect-template.ts => connect.ts} (87%) diff --git a/source/connect-reactive.ts b/source/connect-reactive.ts index 0b4b119..3f361ac 100644 --- a/source/connect-reactive.ts +++ b/source/connect-reactive.ts @@ -13,7 +13,7 @@ import {ConnectBase} from './connect-base'; // For reactive forms (without implicit NgForm) @Directive({ selector: 'form[connect][formGroup]' }) -export class ConnectReactiveDirective extends ConnectBase { +export class ReactiveConnect extends ConnectBase { @Input('formGroup') form; constructor( diff --git a/source/connect-template.ts b/source/connect.ts similarity index 87% rename from source/connect-template.ts rename to source/connect.ts index 4735b0b..ba43ea6 100644 --- a/source/connect-template.ts +++ b/source/connect.ts @@ -15,7 +15,7 @@ import {ConnectBase} from './connect-base'; // For template forms (with implicit NgForm) @Directive({ selector: 'form[connect]:not([formGroup])' }) -export class ConnectTemplateDirective extends ConnectBase { +export class Connect extends ConnectBase { constructor( protected store: FormStore, diff --git a/source/index.ts b/source/index.ts index 56b986b..de0191d 100644 --- a/source/index.ts +++ b/source/index.ts @@ -5,6 +5,6 @@ export * from './form-store'; export * from './configure'; export * from './connect-base'; export * from './connect-reactive'; -export * from './connect-template'; +export * from './connect'; export * from './connect-array'; export * from './module'; diff --git a/source/module.ts b/source/module.ts index 7e9739e..eca3bb4 100644 --- a/source/module.ts +++ b/source/module.ts @@ -3,8 +3,8 @@ import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {NgRedux} from '@angular-redux/store'; -import {ConnectReactiveDirective} from './connect-reactive'; -import {ConnectTemplateDirective} from './connect-template'; +import {ReactiveConnect} from './connect-reactive'; +import {Connect} from './connect'; import {ConnectArray} from './connect-array'; import {FormStore} from './form-store'; @@ -18,13 +18,13 @@ export function formStoreFactory(ngRedux: NgRedux) { ReactiveFormsModule, ], declarations: [ - ConnectTemplateDirective, - ConnectReactiveDirective, + Connect, + ReactiveConnect, ConnectArray, ], exports: [ - ConnectTemplateDirective, - ConnectReactiveDirective, + Connect, + ReactiveConnect, ConnectArray, ], providers: [