Skip to content

Commit

Permalink
Add edit/create member form using angular 2 forms reactive module
Browse files Browse the repository at this point in the history
  • Loading branch information
lthoang committed Nov 22, 2016
1 parent b8b8fdc commit 7b4259a
Show file tree
Hide file tree
Showing 16 changed files with 306 additions and 41 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
/.settings
/ui/*.editorconfig
/src/main/resources/public
/*.DS_Store
3 changes: 2 additions & 1 deletion ui/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ <h1>
{{title}}
</h1>
<nav>
<a routerLink="/members" routerLinkActive="active">Members</a>
<a routerLink="/teams" routerLinkActive="active">All teams</a>
<a routerLink="/members" routerLinkActive="active">All Members</a>
</nav>
<router-outlet></router-outlet>
9 changes: 6 additions & 3 deletions ui/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { FormsModule,ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
Expand All @@ -10,20 +10,23 @@ import {MemberService} from "./member.service";
import {AppRoutingModule} from "./app-routing.module";
import { TeamsComponent } from './teams/teams.component';
import { TeamComponent } from './team/team.component';
import { MemberFormComponent } from './member-form/member-form.component';

@NgModule({
declarations: [
AppComponent,
MemberComponent,
MembersComponent,
TeamsComponent,
TeamComponent
TeamComponent,
MemberFormComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
AppRoutingModule
AppRoutingModule,
ReactiveFormsModule
],
providers: [MemberService],
bootstrap: [AppComponent]
Expand Down
7 changes: 7 additions & 0 deletions ui/src/app/domain/member.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,11 @@ export class Member {
email:string;
mobile:string;
dob:Date;
constructor(id:string,name:Name,email:string,mobile:string,dob:Date) {
this.id = id;
this.name = name;
this.email = email;
this.mobile = mobile;
this.dob = dob;
}
}
6 changes: 6 additions & 0 deletions ui/src/app/domain/name.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,10 @@ export class Name {
middleName:string;
lastName:string;
fullNameFML:string;
constructor(firstName:string, middleName:string, lastName:string) {
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
this.fullNameFML = [firstName,middleName,lastName].join(' ');
}
}
Empty file.
61 changes: 61 additions & 0 deletions ui/src/app/member-form/member-form.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<div *ngIf="member">
<h1>Member details</h1>
<form [formGroup]="memberForm" *ngIf="active" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="firstName">First name</label>
<input type="text" id="firstName" class="form-control"
formControlName="firstName" required>
<div *ngIf="formErrors.firstName" class="alert alert-danger">
{{ formErrors.firstName }}
</div>
</div>
<div class="form-group">
<label for="middleName">Middle name</label>
<input type="text" id="middleName" class="form-control"
formControlName="middleName">
<div *ngIf="formErrors.middleName" class="alert alert-danger">
{{ formErrors.middleName }}
</div>
</div>
<div class="form-group">
<label for="lastName">Last name</label>
<input type="text" id="lastName" class="form-control"
formControlName="lastName" required>
<div *ngIf="formErrors.lastName" class="alert alert-danger">
{{ formErrors.lastName }}
</div>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="text" id="email" class="form-control"
formControlName="email" required>
<div *ngIf="formErrors.email" class="alert alert-danger">
{{ formErrors.email }}
</div>
</div>
<div class="form-group">
<label for="mobile">Mobile</label>
<input type="text" id="mobile" class="form-control"
formControlName="mobile" required>
<div *ngIf="formErrors.mobile" class="alert alert-danger">
{{ formErrors.mobile }}
</div>
</div>
<div class="form-group">
<label for="dob">Date of birth</label>
<input type="date" id="dob" class="form-control"
formControlName="dob" required>
<div *ngIf="formErrors.dob" class="alert alert-danger">
{{ formErrors.dob }}
</div>
</div>

<button type="button" class="btn btn-default"
(click)="goBack()">Cancel
</button>
<button type="submit" class="btn btn-default"
[disabled]="!memberForm.valid">Submit
</button>
</form>
</div>

28 changes: 28 additions & 0 deletions ui/src/app/member-form/member-form.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

import { MemberFormComponent } from './member-form.component';

describe('MemberFormComponent', () => {
let component: MemberFormComponent;
let fixture: ComponentFixture<MemberFormComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ MemberFormComponent ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(MemberFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
128 changes: 128 additions & 0 deletions ui/src/app/member-form/member-form.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import {Component, OnInit, Input} from '@angular/core';
import {FormGroup, FormBuilder, Validators} from '@angular/forms';
import {Router} from '@angular/router';

import {Member} from "../domain/member";
import {Name} from "../domain/name";
import {MemberService} from "../member.service";

@Component({
selector: 'app-member-form',
templateUrl: './member-form.component.html',
styleUrls: ['./member-form.component.css']
})
export class MemberFormComponent implements OnInit {
@Input()
member = new Member(null, new Name('', '', ''), '', '', new Date());
active = true;
memberForm: FormGroup;

membersUrl = '/members';

constructor(private formBuilder: FormBuilder,
private router: Router,
private memberService: MemberService) {
}

onSubmit() {
this.member = this.formToMember(this.memberForm.value);
if (this.member.id != null) {
this.memberService.update(this.member)
.then(() => this.navigateBackToRoot());
} else {
this.memberService.create(this.member)
.then(() => this.navigateBackToRoot());
}
}
private formToMember(value: any): Member {
return new Member(
value.id,
new Name(value.firstName, value.middleName, value.lastName),
value.email,
value.mobile,
value.dob
)
}
navigateBackToRoot(): void {
this.router.navigate([this.membersUrl]);
}

ngOnInit() {
this.buildForm();
}

buildForm(): void {
console.log('something');
this.memberForm = this.formBuilder.group({
'id': [this.member.id],
'firstName': [this.member.name.firstName, [
Validators.required,
Validators.maxLength(24)
]
],
'middleName': [this.member.name.middleName],
'lastName': [this.member.name.lastName, [
Validators.required,
Validators.maxLength(24)
]
],
'email': [this.member.email, Validators.required],
'mobile': [this.member.mobile, Validators.required],
'dob': [this.member.dob, Validators.required]
});

this.memberForm.valueChanges
.subscribe(data => this.onValueChanged(data));

this.onValueChanged(); // (re)set validation messages now
}


onValueChanged(data?: any) {
if (!this.memberForm) {
return;
}
const form = this.memberForm;

for (const field in this.formErrors) {
// clear previous error message (if any)
this.formErrors[field] = '';
const control = form.get(field);

if (control && control.dirty && !control.valid) {
const messages = this.validationMessages[field];
for (const key in control.errors) {
this.formErrors[field] += messages[key] + ' ';
}
}
}
}

formErrors = {
'firstName': '',
'lastName': '',
'email': '',
'mobile': '',
'dob': ''
};

validationMessages = {
'firstName': {
'required': 'First name is required.',
'maxlength': 'First name cannot be more than 24 characters long.'
},
'lastName': {
'required': 'Last name is required.',
'maxlength': 'Last name cannot be more than 24 characters long.'
},
'email': {
'required': 'Email is required.'
},
'mobile': {
'required': 'Mobile is required.'
},
'dob': {
'required': 'Date of birth is required.'
}
};
}
1 change: 1 addition & 0 deletions ui/src/app/member.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,5 @@ export class MemberService {
console.error(errMsg);
return Promise.reject(errMsg);
}

}
62 changes: 34 additions & 28 deletions ui/src/app/member/member.component.html
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
<div *ngIf="member">
<h2>{{member.name.fullNameFML}} details!</h2>
<div><label>ID: </label>{{member.id}}</div>
<div>
<label>First name: </label>
<input [(ngModel)]="member.name.firstName" placeholder="A"/>
<div class="container">
<div *ngIf="!editMode">
<div *ngIf="member">
<h2>{{member.name.fullNameFML}} details!</h2>
<div class="row">
<div class="col-xs-3">First name</div>
<div class="col-xs-9 pull-left">{{member.name.firstName}}</div>
</div>
<div class="row">
<div class="col-xs-3">Middle name</div>
<div class="col-xs-9 pull-left">{{member.name.middleName}}</div>
</div>
<div class="row">
<div class="col-xs-3">Last name</div>
<div class="col-xs-9 pull-left">{{member.name.lastName}}</div>
</div>
<div class="row">
<div class="col-xs-3">Email</div>
<div class="col-xs-9 pull-left">{{member.email}}</div>
</div>
<div class="row">
<div class="col-xs-3">Mobile</div>
<div class="col-xs-9 pull-left">{{member.mobile}}</div>
</div>
<div class="row">
<div class="col-xs-3">Date of birth</div>
<div class="col-xs-9 pull-left">{{member.dob}}</div>
</div>
<br>
<button class="btn btn-default" (click)="edit()">Edit</button>
</div>
</div>
<div>
<label>Middle name: </label>
<input [(ngModel)]="member.name.middleName" placeholder="Van"/>
<div *ngIf="editMode">
<app-member-form [member]="member"></app-member-form>
</div>
<div>
<label>Last name: </label>
<input [(ngModel)]="member.name.lastName" placeholder="Nguyen"/>
</div>
<div>
<label>Email: </label>
<input [(ngModel)]="member.email" placeholder="[email protected]"/>
</div>
<div>
<label>Mobile: </label>
<input [(ngModel)]="member.mobile" placeholder="0912345678"/>
</div>
<div>
<label>Date of birth: </label>
<input type="date" [(ngModel)]="member.dob" placeholder="25-01-1990"/>
</div>
<button (click)="goBack()">Back</button>
<button (click)="save()">Save</button>
</div>
</div>
Loading

0 comments on commit 7b4259a

Please sign in to comment.