Last active
December 27, 2017 17:48
-
-
Save paynoattn/a067fc5c463d3f54129a66d3f078f9aa to your computer and use it in GitHub Desktop.
Angular2 Multipart forms with Component Interaction, Async Operations, and Validation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component, OnInit } from '@angular/core'; | |
import { User, UserProfile } from './models'; | |
// import the user service. This isn't important for our demo, just think of it as an async data source. | |
import { UserService } from './services'; | |
@Component({ | |
selector: 'app', | |
template: ` | |
<user-input [user]="user" (isValid)="userValid = $event"> | |
</user-input> | |
<user-profile-input [userProfile]="userProfile" (isValid)="userProfileValid = $event"> | |
<user-profile-input> | |
<button [disabled]="isFormValid()" (click)="handleSubmit()">Submit</button> | |
` | |
}) | |
export class AppComponent implements OnInit { | |
// here we instantiate our form variables for our models. | |
user: Observable<User>; | |
userProfile: Observable<UserProfile>; | |
// here we instantiate our variables to hide the | |
private userValid: boolean = false; | |
private userProfileValid: boolean = false; | |
private errors: any[] = []; | |
constructor( private userService: UserService ) { } | |
ngOnInit() { | |
// here we are getting our data from a service. | |
this.userService.getUser( | |
data => { | |
this.user = data.user; | |
this.userProfile = data.userProfile; | |
}, | |
error => this.errors.push(error) | |
); | |
} | |
isFormValid() { | |
if ( this.userValid && this.userProfileValid ) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
handleSubmit() { | |
// here we are posting data from the forms to our form. | |
this.userService.postUser( this.user, this.userProfile ); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component, Input, Output, EventEmitter, OnChanges} from '@angular/core'; | |
import { FormBuilder, FormGroup, Validator} from '@angular/forms'; | |
import { User, BlankUser } from '../models'; | |
@Component({ | |
selector: 'user-input', | |
templateUrl: '/userInput/userInput.html' | |
}) | |
export class UserInputComponent implements OnChanges { | |
@Input() user: User; | |
@Output() isValid = new EventEmitter(); | |
userForm: FormGroup | |
constructor( private formBuilder: FormBuilder ) { | |
// construct our form and tell formbuilder what validators we need. | |
this.userForm = this.formBuilder.group({ | |
'name' = [undefined, Validators.required], | |
'email' = [undefined, Validators.required], | |
'password' = [undefined, Validators.required] | |
}); | |
// here we are subscribing to changes to the form. This will fire anytime there is a change in our form. | |
this.userForm.valueChanges.subscribe(() => { | |
this.isValid.emit(this.userForm.valid) | |
}); | |
} | |
onChanges() { | |
/* | |
* ngModel will throw when trying to access properties of our | |
* model when the model itself is undefined. This will happen | |
* often as our application handles async data. | |
*/ | |
if ( !this.user ) { | |
this.user = BlankUser | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<h3>User Input</h3> | |
<form [formGroup]="userForm" novalidate> | |
<input type="text" placeholder="name" formControlName="name" [(ngModel)]="user.name" /> | |
<input type="text" placeholder="email" formControlName="email" [(ngModel)]="user.email" /> | |
<input type="password" placeholder="password" formControlName="password" [(ngModel)]="user.password" /> | |
</form> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component, Input, Output, EventEmitter, OnChanges} from '@angular/core'; | |
import { FormBuilder, FormGroup, Validator} from '@angular/forms'; | |
import { UserProfile, BlankUserProfile } from '../models'; | |
@Component({ | |
selector: 'user-profile-input', | |
templateUrl: '/userProfileInput/userProfileInput.html' | |
}) | |
export class UserProfileInputComponent implements OnChanges { | |
@Input() userProfile: UserProfile; | |
@Output() isValid = new EventEmitter(); | |
private userProfileForm: FormGroup; | |
constructor( private formBuilder: FormBuilder ) { | |
// construct our form and tell formbuilder what validators we need. | |
this.userProfileForm = formBuilder.group({ | |
'address' = [undefinded], | |
'city' = [undefined], | |
'zipcode' = [undefined], | |
'state' = [undefined] | |
}); | |
// here we are subscribing to changes to the form. This will fire anytime there is a change in our form. | |
this.userForm.changes.subscribe(() => { | |
this.isValid.emit(this.userForm.valide); | |
}); | |
} | |
onChanges() { | |
/* | |
* ngModel will throw when trying to access properties of our | |
* model when the model itself is undefined. This will happen | |
* often as our application handles async data. | |
*/ | |
if ( !this.userProfile ) { | |
this.userProfile = BlankUserProfile; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<h3>User Profile Input</h3> | |
<form [formGroup]="userProfileForm" novalidate> | |
<input type="text" placeholder="address" formControlName="address" [(ngModel)]="userProfile.address" /> | |
<input type="text" placeholder="city" formControlName="city" [(ngModel)]="userProfile.city" /> | |
<input type="text" placeholder="zipcode" formControlName="zipcode" [(ngModel)]="userProfile.zipcode" /> | |
<input type="text" placeholder="state" formControlName="state" [(ngModel)]="userProfile.state" /> | |
</form> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment