@larscom/ngrx-form-sync v1.0.0-alpha.11
@larscom/ngrx-form-sync
Easily sync Angular reactive forms to the @ngrx/store with minimal setup.
This library synergizes really well with @larscom/ngrx-store-storagesync
if you would also like to save the form state to a persistant storage solution like sessionStorage
or localStorage
.
Dependencies
@larscom/ngrx-form-sync
depends on @ngrx/store >= 8.0.0 and Angular >=8.0.0.
Setup
- Install package
@larscom/ngrx-form-sync
npm i --save @larscom/ngrx-form-sync
- Add the
NgrxFormSyncModule
to the (feature) module where you are using the reactive forms.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { NgrxFormSyncModule } from '@larscom/ngrx-form-sync';
@NgModule({
imports: [
BrowserModule,
ReactiveFormsModule,
/* import `NgrxFormSyncModule` in every (feature) module */
NgrxFormSyncModule
]
})
export class MyFeatureModule {}
- Register the formSyncReducer
import { NgModule, InjectionToken } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule, ActionReducerMap, MetaReducer, ActionReducer } from '@ngrx/store';
import { formSyncReducer, IFormSyncState } from '@larscom/ngrx-form-sync';
import * as fromApp from './store/reducer';
export const FORM_SYNC_REDUCER = new InjectionToken<ActionReducer<IFormSyncState>>('FORM_SYNC_REDUCER');
@NgModule({
imports: [
BrowserModule,
StoreModule.forRoot({ app: fromApp.reducer }),
/* register the formSyncReducer */
StoreModule.forFeature('form', FORM_SYNC_REDUCER)
],
providers: [
{
provide: FORM_SYNC_REDUCER,
useValue: formSyncReducer
}
]
})
export class AppModule {}
Usage
Add formGroupId
to the element where formGroup
is present. Without formGroupId
, the form doesn't get synced.
<form [formGroup]="myFormGroup" [formGroupId]="'myFormGroup'">
<div>
<input formControlName="firstName" />
<input formControlName="lastName" />
</div>
<button type="submit">Submit</button>
</form>
If you want to exclude / ignore certian form controls you can't use the formControlName
attribute.
Instead bind to formControl
and set formControlSync
to false
.
<form [formGroup]="myFormGroup" [formGroupId]="'myFormGroup'">
<div>
/* firstName will not get synced */
<input [formControl]="myFormGroup.get('firstName')" [formControlSync]="false" />
<input formControlName="lastName" />
</div>
<button type="submit">Submit</button>
</form>
Get the form value anywhere in your app
import { Component } from '@angular/core';
import { getFormSyncValue } from '@larscom/ngrx-form-sync';
import { Store, select } from '@ngrx/store';
@Component({
selector: 'app-my-component',
template: `
<div>
<h1>My Form Value</h1>
{{ myFormValue$ | async | json }}
</div>
`,
styleUrls: ['my-component.component.scss']
})
export class MyComponent {
constructor(private store: Store<any>) {}
myFormValue$ = this.store.pipe(select(getFormSyncValue, { id: 'myFormGroup' }));
}
Update the form via the action dispatcher
import { Component } from '@angular/core';
import { setForm, patchForm, resetForm, deleteForm } from '@larscom/ngrx-form-sync';
import { Store, select } from '@ngrx/store';
@Component({
selector: 'app-my-component',
templateUrl: 'my-component.component.html'
styleUrls: ['my-component.component.scss']
})
export class MyComponent {
constructor(private store: Store<any>) {}
/* patch form value, lastName can be omitted */
patchValue(): void {
const value = {
firstName: 'Jan',
//lastName: 'Jansen'
};
this.store.dispatch(patchForm({ id: 'myFormGroup', value }));
}
/* sets the initial form value */
setValue(): void {
const value = {
firstName: 'Jan',
lastName: 'Jansen'
};
this.store.dispatch(setForm({ id: 'myFormGroup', value }));
}
/* reset form value (sets every property to null) */
resetValue(): void {
this.store.dispatch(resetForm({ id: 'myFormGroup' }));
}
/* remove form value from store */
deleteValue(): void {
this.store.dispatch(deleteForm({ id: 'myFormGroup' }));
}
}
Configuration
You can override the default configuration on component level
import { Component } from '@angular/core';
import { IFormSyncConfig, FORM_SYNC_CONFIG } from '@larscom/ngrx-form-sync';
const formSyncConfig: IFormSyncConfig = {
/* Only sync to the store when submitting the form. */
syncOnSubmit: true
};
@Component({
selector: 'app-my-component',
templateUrl: 'my-component.component.html',
styleUrls: ['my-component.component.scss'],
providers: [
{
provide: FORM_SYNC_CONFIG,
useValue: formSyncConfig
}
]
})
export class MyComponent {}
export interface IFormSyncConfig {
/**
* Only sync to the store when submitting the form.
*/
syncOnSubmit?: boolean;
/**
* Only sync to the store when the form status is valid.
*/
syncValidOnly?: boolean;
/**
* Sync the raw form value to the store (this will include disabled form controls)
*/
syncRawValue?: boolean;
}
FormGroup Directive API
Attribute | Type | Default | Required | Description |
---|---|---|---|---|
formGroupId | string | null | yes | The unique ID for the form group. |
formGroupSync | boolean | true | no | Whether the form group value should sync to the @ngrx/store. |
FormControl Directive API
Attribute | Type | Default | Required | Description |
---|---|---|---|---|
formControlSync | boolean | true | no | Whether the form control value should sync to the @ngrx/store. |
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago