Skip to content

Instantly share code, notes, and snippets.

@arjunasuresh3
Forked from NetanelBasal/add-story-form.ts
Created October 13, 2020 16:37
Show Gist options
  • Save arjunasuresh3/9cc1d50874f62f2c61c7a3d02e4b0a86 to your computer and use it in GitHub Desktop.
Save arjunasuresh3/9cc1d50874f62f2c61c7a3d02e4b0a86 to your computer and use it in GitHub Desktop.
@Component({
selector: 'add-story-form',
template: `
<div class="container">
<h1>New Story</h1>
<form [formGroup]="newStory"
(submit)="submit($event)"
(success)="onSuccess()"
(error)="onError($event)"
connectForm="newStory">
<div class="form-group">
<input type="text" formControlName="title" class="form-control" placeholder="Title">
</div>
<div class="form-group">
<textarea formControlName="description"
placeholder="Story.."
cols="10" rows="3" class="form-control"></textarea>
</div>
<div class="form-group">
<input type="checkbox" formControlName="draft"> Draft
</div>
<select formControlName="category">
<option *ngFor="let option of options" [ngValue]="option.id">{{option.label}}</option>
</select>
<button [disabled]="newStory.invalid" class="btn btn-primary" type="submit">Submit</button>
</form>
<div class="alert alert-success" *ngIf="success">Success!</div>
<div class="alert alert-danger" *ngIf="error">{{error}}</div>
</div>
`
})
export class NewStoryComponent {
options = [{ id: 1, label: 'Category One' }, { id: 2, label: 'Category Two' }]
onError( error ) {
this.error = error;
}
onSuccess() {
this.success = true;
}
ngOnInit() {
this.newStory = new FormGroup({
title: new FormControl(null, Validators.required),
description: new FormControl(null, Validators.required),
draft: new FormControl(false),
category: new FormControl(this.options[1].id, Validators.required)
});
}
submit() {
this.success = false;
this.store.dispatch({
type: 'ADD_STORY'
})
}
}
import { Directive, EventEmitter, Input, Output } from '@angular/core';
import { FormGroupDirective } from '@angular/forms';
import { Store } from '@ngrx/store';
import { Subscription } from 'rxjs/Subscription';
import { Actions } from '@ngrx/effects';
const FORM_SUBMIT_SUCCESS = 'FORM_SUBMIT_SUCCESS';
const FORM_SUBMIT_ERROR = 'FORM_SUBMIT_ERROR';
const UPDATE_FORM = 'UPDATE_FORM';
export const formSuccessAction = path => ({
type: FORM_SUBMIT_SUCCESS,
payload: {
path
}
});
export const formErrorAction = ( path, error ) => ({
type: FORM_SUBMIT_ERROR,
payload: {
path,
error
}
});
@Directive({
selector: '[connectForm]'
})
export class ConnectFormDirective {
@Input('connectForm') path : string;
@Input() debounce : number = 300;
@Output() error = new EventEmitter();
@Output() success = new EventEmitter();
formChange : Subscription;
formSuccess : Subscription;
formError : Subscription;
constructor( private formGroupDirective : FormGroupDirective,
private actions$ : Actions,
private store : Store<any> ) {
}
ngOnInit() {
this.store.select(state => state.forms[this.path]).take(1).subscribe(val => {
this.formGroupDirective.form.patchValue(val);
});
this.formChange = this.formGroupDirective.form.valueChanges
.debounceTime(this.debounce).subscribe(value => {
this.store.dispatch({
type: UPDATE_FORM,
payload: {
value,
path: this.path,
}
});
});
this.formSuccess = this.actions$
.ofType(FORM_SUBMIT_SUCCESS)
.filter(( { payload } ) => payload.path === this.path)
.subscribe(() => {
this.formGroupDirective.form.reset();
this.success.emit();
});
this.formError = this.actions$
.ofType(FORM_SUBMIT_ERROR)
.filter(( { payload } ) => payload.path === this.path)
.subscribe(( { payload } ) => this.error.emit(payload.error))
}
ngOnDestroy() {
this.formChange.unsubscribe();
this.formError.unsubscribe();
this.formSuccess.unsubscribe();
}
}
import { from } from 'rxjs/observable/from';
import { formErrorAction, formSuccessAction } from '../connect-form.directive';
@Injectable()
export class StoryEffects {
constructor( private storyService : StoryService,
private store : Store<any>,
private actions$ : Actions ) {
}
@Effect() addStory$ = this.actions$
.ofType('ADD_STORY')
.switchMap(action =>
this.storyService.add(action.payload)
.switchMap(story => (from([{
type: 'ADD_STORY_SUCCESS'
}, formSuccessAction('newStory')])))
.catch(err => (of(formErrorAction('newStory', err))))
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment