This commit is contained in:
byung eun park 2019-08-28 19:22:54 +09:00
parent fd24101f0e
commit 66d3cc80b1
8 changed files with 253 additions and 233 deletions

View File

@ -18,9 +18,12 @@ export class UsersDataSource extends DataSource<User> {
private paginator: MatPaginator, private paginator: MatPaginator,
private sort: MatSort private sort: MatSort
) { ) {
User;
super(); super();
User;
} }
User;
User;
// Filter // Filter
get filter(): string { get filter(): string {
return this.filterSubject.value; return this.filterSubject.value;

View File

@ -1,7 +1,10 @@
<div id="forms" class="page-layout simple fullwidth" fxLayout="column"> <div id="forms" class="page-layout simple fullwidth" fxLayout="column">
<!-- HEADER --> <!-- HEADER -->
<div class="header accent p-24 h-160" fxLayout="row" fxLayoutAlign="start center"> <div
class="header accent p-24 h-160"
fxLayout="row"
fxLayoutAlign="start center"
>
<div fxLayout="column" fxLayoutAlign="center start"> <div fxLayout="column" fxLayoutAlign="center start">
<div fxLayout="row" fxLayoutAlign="start center"> <div fxLayout="row" fxLayoutAlign="start center">
<mat-icon class="secondary-text s-18">home</mat-icon> <mat-icon class="secondary-text s-18">home</mat-icon>
@ -15,164 +18,123 @@
<!-- CONTENT --> <!-- CONTENT -->
<div class="content p-24"> <div class="content p-24">
<div class="h1"> <div class="h1">
Reactive Forms 회원가입
</div> </div>
<p class="pt-16 pb-32"> <div
Angular reactive forms facilitate a reactive style of programming that favors explicit management of the class="mb-24"
data flowing between a non-UI data model (typically retrieved from a server) and a UI-oriented form model fxLayout="column"
that retains the states and values of the HTML controls on screen. Reactive forms offer the ease of using fxLayoutAlign="start"
reactive patterns, testing, and validation. fxLayout.gt-md="row"
</p> >
<div class="h1 pt-32"> <form
Horizontal Stepper class="mat-card mat-elevation-z4 p-24 mr-24"
fxLayout="column"
fxLayoutAlign="start"
fxFlex="1 0 auto"
name="registerForm"
[formGroup]="registerForm"
(ngSubmit)="registUser()"
>
<div class="h2 mb-24">기본정보</div>
<div fxLayout="row" fxLayoutAlign="start center" fxFlex="1 0 auto">
<mat-form-field appearance="outline" fxFlex="50" class="pr-4">
<mat-label>아이디</mat-label>
<input matInput formControlName="username" />
<mat-icon matSuffix class="secondary-text">account_circle</mat-icon>
<mat-error>아이디는 필수 사항입니다!</mat-error>
</mat-form-field>
<mat-form-field appearance="outline" fxFlex="50" class="pl-4">
<mat-label>핸드폰</mat-label>
<input matInput formControlName="phone" />
<mat-icon matSuffix class="secondary-text">phone</mat-icon>
<mat-error>핸드폰은 필수 사항입니다!</mat-error>
</mat-form-field>
</div> </div>
<div class="mb-24" fxLayout="column" fxLayoutAlign="start" fxLayout.gt-md="row">
<div fxLayout="row" fxLayoutAlign="start center" fxFlex="1 0 auto">
<!-- <mat-form-field appearance="outline" fxFlex="50" class="pr-4">
<p class="pb-32"> <mat-label>패스워드</mat-label>
Angular Material's stepper provides a wizard-like workflow by dividing content into logical steps. <input matInput type="password" formControlName="password" />
<code>mat-horizontal-stepper</code> selector can be used to create a horizontal stepper. <mat-icon matSuffix class="secondary-text">vpn_key</mat-icon>
</p> --> <mat-error>
패스워드는 필수 사항입니다!
<div class="horizontal-stepper-wrapper"> </mat-error>
<!-- HORIZONTAL STEPPER EXAMPLE -->
<mat-horizontal-stepper class="mat-elevation-z4" [linear]="true">
<mat-step [stepControl]="horizontalStepperStep1">
<form fxLayout="column" [formGroup]="horizontalStepperStep1">
<ng-template matStepLabel>Fill out your name</ng-template>
<div fxFlex="1 0 auto" fxLayout="column">
<mat-form-field appearance="outline" fxFlex="100">
<mat-label>First Name</mat-label>
<input matInput formControlName="firstName" required>
<mat-error>First Name is required!</mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field appearance="outline" fxFlex="100"> <mat-form-field appearance="outline" fxFlex="50" class="pl-4">
<mat-label>Last Name</mat-label> <mat-label>패스워드 (확인)</mat-label>
<input matInput formControlName="lastName" required> <input matInput type="password" formControlName="passwordConfirm" />
<mat-error>Last Name is required!</mat-error> <mat-icon matSuffix class="secondary-text">vpn_key</mat-icon>
<mat-error
*ngIf="registerForm.get('passwordConfirm').hasError('required')"
>
패스워드 확인은 필수 사항입니다!
</mat-error>
<mat-error
*ngIf="
!registerForm.get('passwordConfirm').hasError('required') &&
registerForm
.get('passwordConfirm')
.hasError('passwordsNotMatching')
"
>
패스워드가 일치하지 않습니다!
</mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
<div fxLayout="row" fxLayoutAlign="center center"> <div fxLayout="row" fxLayoutAlign="start center" fxFlex="1 0 auto">
<button mat-raised-button matStepperNext type="button" color="accent"> <mat-form-field appearance="outline" fxFlex="50">
Next <mat-label>닉네임</mat-label>
<input matInput formControlName="nickname" required />
<mat-icon matSuffix class="secondary-text">account_circle</mat-icon>
<mat-error>닉네임은 필수 사항입니다!!</mat-error>
</mat-form-field>
<mat-form-field appearance="outline" fxFlex="50" class="px-8">
<mat-label>이메일</mat-label>
<input matInput formControlName="email" />
<mat-icon matSuffix class="secondary-text">mail</mat-icon>
</mat-form-field>
</div>
<div fxLayout="row wrap" fxLayoutAlign="start center" fxFlex="1 0 auto">
<mat-form-field appearance="outline" fxFlex="100">
<mat-label>비고</mat-label>
<textarea
matInput
formControlName="descriptions"
placeholder="부가적인 설명"
></textarea>
</mat-form-field>
</div>
<button
mat-raised-button
color="accent"
class="submit-button"
aria-label="CREATE AN ACCOUNT"
[disabled]="registerForm.invalid"
>
CREATE AN ACCOUNT
</button> </button>
</div>
</form> </form>
<div class="mat-card form-errors-model p-24 mat-elevation-z4">
</mat-step> <div class="h2 mb-24">계좌정보</div>
<pre>계좌정보</pre>
<mat-step [stepControl]="horizontalStepperStep2">
<form fxLayout="column" [formGroup]="horizontalStepperStep2">
<ng-template matStepLabel>Fill out your address</ng-template>
<div fxFlex="1 0 auto" fxLayout="row">
<mat-form-field appearance="outline" fxFlex="100">
<mat-label>Address</mat-label>
<textarea matInput formControlName="address" required>
1600 Amphitheatre Pkwy
</textarea>
<mat-error>Address is required!</mat-error>
</mat-form-field>
</div> </div>
<div fxLayout="row" fxLayoutAlign="center center">
<button class="mr-8" mat-raised-button matStepperPrevious type="button" color="accent">
Previous
</button>
<button mat-raised-button matStepperNext type="button" color="accent">
Next
</button>
</div>
</form>
</mat-step>
<mat-step [stepControl]="horizontalStepperStep3">
<form fxLayout="column" [formGroup]="horizontalStepperStep3">
<ng-template matStepLabel>Fill out your address</ng-template>
<div fxFlex="1 0 auto" fxLayout="column">
<mat-form-field appearance="outline" fxFlex="100">
<mat-label>City</mat-label>
<input matInput formControlName="city" required>
<mat-error>City is required!</mat-error>
</mat-form-field>
<mat-form-field appearance="outline" fxFlex="100">
<mat-label>State</mat-label>
<input matInput formControlName="state" required>
<mat-error>State is required!</mat-error>
</mat-form-field>
<mat-form-field appearance="outline" fxFlex="100">
<mat-label>Postal Code</mat-label>
<input matInput #postalCode2 formControlName="postalCode" maxlength="5" required>
<mat-hint align="end">{{postalCode2.value.length}} / 5</mat-hint>
<mat-error>Postal Code is required!</mat-error>
</mat-form-field>
</div>
<div fxLayout="row" fxLayoutAlign="center center">
<button class="mr-8" mat-raised-button matStepperPrevious type="button" color="accent">
Previous
</button>
<button mat-raised-button matStepperNext type="button" color="accent">
Next
</button>
</div>
</form>
</mat-step>
<mat-step>
<ng-template matStepLabel>Done</ng-template>
<div class="h2 m-16" fxLayout="row" fxLayoutAlign="center center">
Thank your for filling out our form.
</div>
<div fxLayout="row" fxLayoutAlign="center center">
<button class="mr-8" mat-raised-button matStepperPrevious type="button" color="accent">
Previous
</button>
<button mat-raised-button type="button" color="accent" (click)="finishHorizontalStepper()">
Finish
</button>
</div>
</mat-step>
</mat-horizontal-stepper>
<!-- / HORIZONTAL STEPPER EXAMPLE --> <!-- / HORIZONTAL STEPPER EXAMPLE -->
</div>
<div class="mat-card form-errors-model p-24 mat-elevation-z4">
<div class="h2 mb-24">Reactive Form Model</div>
<pre>아아아다다다다다다다</pre>
</div>
<div class="mat-card form-errors-model p-24 mat-elevation-z4">
<div class="h2 mb-24">Reactive Form Model</div>
<pre>아아아다다다다다다다</pre>
</div> </div>
<!-- / CONTENT --> <!-- / CONTENT -->
</div> </div>
</div>
</div> </div>

View File

@ -1,7 +1,5 @@
:host { :host {
.content { .content {
form { form {
width: 100%; width: 100%;
max-width: 800px !important; max-width: 800px !important;

View File

@ -1,15 +1,28 @@
import { Component, OnDestroy, OnInit } from '@angular/core'; import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import {
AbstractControl,
FormBuilder,
FormGroup,
ValidationErrors,
ValidatorFn,
Validators
} from '@angular/forms';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/internal/operators';
import { take } from 'rxjs/operators';
import { fuseAnimations } from 'src/@fuse/animations';
import { User } from 'src/modules/user/model/user.model';
import { SignupRequest } from 'src/modules/auth/model/auth-signup-request.model';
import { AuthService } from 'src/modules/auth/service/auth.service';
@Component({ @Component({
selector: 'app-user-regist', selector: 'app-user-regist',
templateUrl: './user-regist.component.html', templateUrl: './user-regist.component.html',
styleUrls: ['./user-regist.component.scss'] styleUrls: ['./user-regist.component.scss'],
encapsulation: ViewEncapsulation.Emulated,
animations: fuseAnimations
}) })
export class UserRegistComponent implements OnInit, OnDestroy { export class UserRegistComponent implements OnInit, OnDestroy {
registerForm: FormGroup;
form: FormGroup;
// Horizontal Stepper // Horizontal Stepper
horizontalStepperStep1: FormGroup; horizontalStepperStep1: FormGroup;
horizontalStepperStep2: FormGroup; horizontalStepperStep2: FormGroup;
@ -25,7 +38,8 @@ export class UserRegistComponent implements OnInit, OnDestroy {
* @param {FormBuilder} _formBuilder * @param {FormBuilder} _formBuilder
*/ */
constructor( constructor(
private _formBuilder: FormBuilder private _formBuilder: FormBuilder,
private _authService: AuthService
) { ) {
// Set the private defaults // Set the private defaults
this._unsubscribeAll = new Subject(); this._unsubscribeAll = new Subject();
@ -40,37 +54,23 @@ export class UserRegistComponent implements OnInit, OnDestroy {
*/ */
ngOnInit() { ngOnInit() {
// Reactive Form // Reactive Form
this.form = this._formBuilder.group({ this.registerForm = this._formBuilder.group({
company: [ username: ['', Validators.required],
{ phone: ['', Validators.required],
value: 'Google', password: ['', Validators.required],
disabled: true passwordConfirm: ['', [Validators.required, confirmPasswordValidator]],
}, Validators.required nickname: ['', Validators.required],
], email: [''],
firstName: ['', Validators.required], descriptions: ['']
lastName: ['', Validators.required],
address: ['', Validators.required],
address2: ['', Validators.required],
city: ['', Validators.required],
state: ['', Validators.required],
postalCode: ['', [Validators.required, Validators.maxLength(5)]],
country: ['', Validators.required]
}); });
// Horizontal Stepper form steps // Update the validity of the 'passwordConfirm' field
this.horizontalStepperStep1 = this._formBuilder.group({ // when the 'password' field changes
firstName: ['', Validators.required], this.registerForm
lastName: ['', Validators.required] .get('password')
}); .valueChanges.pipe(takeUntil(this._unsubscribeAll))
.subscribe(() => {
this.horizontalStepperStep2 = this._formBuilder.group({ this.registerForm.get('passwordConfirm').updateValueAndValidity();
address: ['', Validators.required]
});
this.horizontalStepperStep3 = this._formBuilder.group({
city: ['', Validators.required],
state: ['', Validators.required],
postalCode: ['', [Validators.required, Validators.maxLength(5)]]
}); });
} }
@ -83,21 +83,44 @@ export class UserRegistComponent implements OnInit, OnDestroy {
this._unsubscribeAll.complete(); this._unsubscribeAll.complete();
} }
// ----------------------------------------------------------------------------------------------------- registUser(): void {
// @ Public methods let user: SignupRequest = <SignupRequest>this.registerForm.value;
// ----------------------------------------------------------------------------------------------------- console.log(user);
this._authService
/** .signup(user)
* Finish the horizontal stepper .pipe(take(1))
*/ .subscribe(
finishHorizontalStepper(): void { res => {
alert('You have finished the horizontal stepper!'); console.log(res);
},
err => {
console.log(err);
}
);
}
} }
/** export const confirmPasswordValidator: ValidatorFn = (
* Finish the vertical stepper control: AbstractControl
*/ ): ValidationErrors | null => {
finishVerticalStepper(): void { if (!control.parent || !control) {
alert('You have finished the vertical stepper!'); return null;
} }
const password = control.parent.get('password');
const passwordConfirm = control.parent.get('passwordConfirm');
if (!password || !passwordConfirm) {
return null;
} }
if (passwordConfirm.value === '') {
return null;
}
if (password.value === passwordConfirm.value) {
return null;
}
return { passwordsNotMatching: true };
};

View File

@ -0,0 +1,8 @@
export interface SignupRequest {
username: string;
nickname: string;
email: string;
password: string;
descriptions: string;
phone: string;
}

View File

@ -7,6 +7,7 @@ import { JwtSigninResponse } from '../model/jwt-signin-response.model';
import { CookieService } from 'ngx-cookie-service'; import { CookieService } from 'ngx-cookie-service';
import { API_BASE_URL } from 'src/modules/common/type/injection-token.type'; import { API_BASE_URL } from 'src/modules/common/type/injection-token.type';
import { SignupRequest } from '../model/auth-signup-request.model';
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class AuthService { export class AuthService {
@ -16,6 +17,31 @@ export class AuthService {
@Inject(API_BASE_URL) private apiBaseUrl: string @Inject(API_BASE_URL) private apiBaseUrl: string
) {} ) {}
public signup(signupInfo: SignupRequest): Observable<any> {
const ll = JSON.stringify(signupInfo);
const username = signupInfo.username;
const password = signupInfo.password;
const email = signupInfo.email;
const phone = signupInfo.phone;
const descriptions = signupInfo.descriptions;
const nickname = signupInfo.nickname;
return this.httpClient
.post<any>(`${this.apiBaseUrl}/auth/signup`, {
username,
nickname,
email,
password,
descriptions,
phone
})
.pipe(
map(res => {
console.log('signup response: ' + res);
return res;
})
);
}
public authenticate( public authenticate(
username: string, username: string,
password: string password: string

View File

@ -14,5 +14,6 @@ export interface User extends DateAudit {
otpKey?: string; otpKey?: string;
otp?: string; otp?: string;
requireReset?: boolean; requireReset?: boolean;
phone?: string;
descriptions?: string;
} }

View File

@ -7,7 +7,6 @@ import { Page } from 'src/modules/common/data/model/page';
@Injectable() @Injectable()
export class UserService { export class UserService {
constructor( constructor(
@Inject(API_BASE_URL) private apiBaseUrl: string, @Inject(API_BASE_URL) private apiBaseUrl: string,
private httpClient: HttpClient private httpClient: HttpClient