๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ’ป Frontend/Angular

[Angular] ํšŒ์›๊ฐ€์ž… ์ž…๋ ฅํ™”๋ฉด ๋งŒ๋“ค์–ด๋ณด๊ธฐ (Register Validation Form)

by Fomagran ๐Ÿ’ป 2022. 3. 24.
728x90
๋ฐ˜์‘ํ˜•

์•ˆ๋…•ํ•˜์„ธ์š” Foma ๐Ÿ’ป  ์ž…๋‹ˆ๋‹ค.

 

์˜ค๋Š˜์€ ํšŒ์›๊ฐ€์ž…์„ ํ•  ๋•Œ ์ •ํ•ด์ง„ ๊ทœ์น™์— ๋งž๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์‚ฌํ•˜๋Š” ํ™”๋ฉด ํผ์„ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋ฐ”๋กœ ์‹œ์ž‘ํ• ๊ฒŒ์š”~


Set up angular material

 

์•ต๊ทค๋Ÿฌ์—์„œ๋Š” ๋จธํ„ฐ๋ฆฌ์–ผ ๋””์ž์ธ๋œ UI ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 

์•„๋ž˜ ์‚ฌ์ดํŠธ๋ฅผ ์ด๋™ํ•˜์‹œ๋ฉด ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ API๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

Angular Material

UI component infrastructure and Material Design components for Angular web applications.

material.angular.io

 

ํ„ฐ๋ฏธ๋„์— angular material์„ ์„ค์น˜ํ•ด ์ค๋‹ˆ๋‹ค.

 

ng add @angular/material

 

์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋œ ๋’ค์— ๋ช‡๊ฐ€์ง€ ์ถ”๊ฐ€์ ์œผ๋กœ ์„ค์น˜ํ•  ๊ฑด์ง€ ๋ฌผ์–ด๋ณด๋Š”๋ฐ์š”.

 

Would like to proceed? (๊ณ„์† ์ง„ํ–‰ํ• ๊ฑฐ์•ผ?) yes

 

Choose a prebuilt theme name, or "custom" for a custom theme (๋„ˆ๊ฐ€ ์›ํ•˜๋Š” ํ…Œ๋งˆ ์ƒ‰๊น”์ด๋‚˜, ์ปค์Šคํ…€ ํ…Œ๋งˆ ๊ณจ๋ผ๋ด)

 

๋ง˜์— ๋“œ๋Š” ํ…Œ๋งˆ ๊ณ ๋ฅด์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

Set up global Angular Material typography styles? (๋„ˆ ์•ต๊ทค๋Ÿฌ ํƒ€์ดํฌ๊ทธ๋ž˜ํ”ผ ์‚ฌ์šฉํ• ๋ž˜?) yes

 

Set up browser animations for Angular Material? (์•ต๊ทค๋Ÿฌ ๋จธํ„ฐ๋ฆฌ์–ผ ๋ธŒ๋ผ์šฐ์ € ์• ๋‹ˆ๋ฉ”์ด์…˜ ์„ค์น˜ํ• ๋ž˜?) yes

 


Set up material components

 

ํšŒ์›๊ฐ€์ž… ํ™”๋ฉด์—์„œ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๋จผ์ € ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

1. Forms Field

 

์ž…๋ ฅ ์–‘์‹์˜ ํ•„๋“œ์˜ ๊ฐ’์„ ์„ธํŒ…ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค/

 

2. Input

 

์ž…๋ ฅํ•˜๋Š” ์ฐฝ์„ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

 

3. Button

 

ํšŒ์›๊ฐ€์ž… ๋ฒ„ํŠผ์„ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

 

app.module.ts

 

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ์ปดํฌ๋„ŒํŠธ๋“ค์„ import ํ•ด์ค๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  Material Component๋Š” ์•„๋‹ˆ์ง€๋งŒ ์œ„ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ReactiveFormsModule, FormsModule๋ฅผ import ํ•ด์ค๋‹ˆ๋‹ค.

 

import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';

 

NgModule์—๋„ ์ถ”๊ฐ€์‹œ์ผœ ์ค๋‹ˆ๋‹ค.

 

@NgModule({
	...
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    MatFormFieldModule,
    MatInputModule,
    MatButtonModule,
    ReactiveFormsModule, 
    FormsModule
  ],
	...
})

Create register component

 

ํšŒ์›๊ฐ€์ž… ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•ด ์ค๋‹ˆ๋‹ค.

 

ng g c pages/register

 

register.component.html

 

์œ„์—์„œ ์„ค์น˜ํ•ด์ค€ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ํ™œ์šฉํ•˜์—ฌ ํšŒ์›๊ฐ€์ž… ํ™”๋ฉด ๋ ˆ์ด์•„์›ƒ์„ ์žก์•„์ค๋‹ˆ๋‹ค.

 

<div class="container">
    <div class="form-container">
      <div class="title">Register</div>
      <form>
        <mat-form-field appearance="outline">
          <mat-label>Enter your email</mat-label>
          <input matInput formControlName="email" />
        </mat-form-field>
        <mat-form-field appearance="outline">
          <mat-label>Enter your password</mat-label>
          <input type="password" matInput formControlName="password" />
        </mat-form-field>
      </form>
      <div class="buttons-container">
        <button
          mat-raised-button
          class="register-button">
          Register
        </button>
      </div>
    </div>
  </div>

register.component.css

 

.container {
    display: flex;
    flex-direction: row;
    width: 100%;
    height: 100%;
    justify-content: center;
    align-items: center;
  }
  
  .form-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-top: 10vh;
    margin-bottom: 10vh;
    background-color: white;
    box-shadow: 0 2px 6px 1px rgba(0, 0, 0, 0.2);
    padding: 50px;
  }
  
  form {
    display: flex;
    flex-direction: column;
  }
  
  .title {
    font-size: 22px;
    margin-bottom: 20px;
  }
  
  mat-form-field {
    width: 20vw;
  }
  
  .buttons-container {
    display: flex;
    flex-direction: column;
    width: 100%;
    align-items: center;
  }
  
  .buttons-container > p {
    margin-top: 10px;
  }

Register Layout

 

์‹คํ–‰์‹œ์ผœ๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ํ™”๋ฉด์ด ๋‚˜์˜ต๋‹ˆ๋‹ค.


Create form validator

 

์ด์ œ Input์ฐฝ์— ์–ด๋– ํ•œ ๊ฐ’์„ ์ž…๋ ฅํ–ˆ์„ ๋•Œ ์ •ํ•ด์ง„ ๊ทœ์น™๋Œ€๋กœ ์ž‘์„ฑํ–ˆ๋Š”์ง€ ๊ฒ€์‚ฌํ•  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

FormBuilder๋ฅผ import ํ•ด์ฃผ๊ณ ,

 

import { FormBuilder } from '@angular/forms';

 

์ƒ์„ฑ์ž์— formBuilder๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

 

  constructor(private formBuilder:FormBuilder,) { }

 

formBuilder๋Š” form์— ๊ด€๋ จ๋œ formControl,validator ๋“ฑ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค ์ž…๋‹ˆ๋‹ค.

 

registerform์˜ ๊ทœ์น™๋“ค์„ ์ƒ์„ฑํ•ด ์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์•„๋ž˜์™€ ๊ฐ™์ด form์„ ๋งŒ๋“ค์–ด์ฃผ๊ณ , group์„ ํ†ตํ•ด์„œ ๊ฐ input ๊ฐ’์˜ ๊ทœ์น™๋“ค์„ ์ ์–ด์ค๋‹ˆ๋‹ค.

 

  registerForm = this.formBuilder.group({
    //๋ฐ˜๋“œ์‹œ ์ž…๋ ฅ๋˜์–ด์•ผ ํ•˜๋ฉฐ, ์ด๋ฉ”์ผ ํ˜•์‹์— ๋งž์ถฐ ์ž‘์„ฑํ•ด์•ผ ํ•จ.
    email: ['', [Validators.required, Validators.email]],
    //๋ฐ˜๋“œ์‹œ ์ž…๋ ฅ๋˜์–ด์•ผ ํ•˜๋ฉฐ, ์ตœ์†Œ 6๊ธ€์ž ์ด์ƒ์ด์–ด์•ผ ํ•จ.
    password: ['', [Validators.required, Validators.minLength(6)]],
  });

register.component.html

 

htmlํŒŒ์ผ์—์„œ form์— ์œ„์—์„œ ๋งŒ๋“  registerForm์„ ์ ์šฉ์‹œ์ผœ ์ค๋‹ˆ๋‹ค.

      <form  [formGroup]="registerForm">
        ...
      </form>

 

๊ทธ๋ฆฌ๊ณ  ์‹คํ–‰์‹œ์ผœ ๋ณด๋ฉด registerForm์— ์ ์šฉํ•œ ๊ทœ์น™๋Œ€๋กœ ์ž‘์„ฑํ•˜์ง€ ์•Š์œผ๋ฉด ๋นจ๊ฐ„์ƒ‰์œผ๋กœ, ๊ทœ์น™์„ ์ค€์ˆ˜ํ•˜๋ฉด ํŒŒ๋ž€์ƒ‰์œผ๋กœ Input ์ฐฝ์ด ๋ฐ”๋€Œ๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 


Button activate/deactivate

 

์ž…๋ ฅํ•œ ๊ฐ’๋“ค์ด ์ •ํ•ด์ง„ ๊ทœ์น™์„ ์ค€์ˆ˜ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๋ฒ„ํŠผ์ด ๋น„ํ™œ์„ฑํ™” ๋˜๊ณ , ์ค€์ˆ˜ํ•œ๋‹ค๋ฉด ํ™œ์„ฑํ™” ๋˜๊ฒŒ ํ•˜๋ฉด ๋” ๋‚ซ๊ฒ ์ฃ ?

 

๋ฐ”๋กœ ์•ž์„œ ๋งŒ๋“ค์—ˆ๋˜ registerForm์„ ์ด์šฉํ•ด์„œ ๋ฒ„ํŠผ๊ณผ ๋ฐ”์ธ๋”ฉ ์‹œ์ผœ์ค๋‹ˆ๋‹ค.

 

register.component.html

 

๋ฒ„ํŠผ์„ ๋น„ํ™œ์„ฑํ™” ์‹œํ‚ค๋„๋ก ํ•˜๋Š” disabled์™€ registerForm์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ์•„๋‹Œ์ง€๋ฅผ ์•Œ๋ ค์ค„ .invalid ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ”์ธ๋”ฉ ํ•ด์ค๋‹ˆ๋‹ค.

 

        ...
        <button
        [disabled]="registerForm.invalid"
          mat-raised-button
          class="register-button">
          Register
        </button>
        ...

 

์ด๋ ‡๊ฒŒ ๋ฐ”์ธ๋”ฉ ์‹œํ‚ค๋ฉด ํผ์ด ๊ทœ์น™์„ ์ค€์ˆ˜ํ•˜๋Š”์ง€ ์•ˆํ•˜๋Š”์ง€์— ๋”ฐ๋ผ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฒ„ํŠผ์ด ํ™œ์„ฑํ™”/๋น„ํ™œ์„ฑํ™” ๋˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 


Show error messages below

 

์‚ฌ์šฉ์ž์—๊ฒŒ ์–ด๋–ค ๊ทœ์น™์„ ์ง€์ผœ์•ผ ํ•˜๋Š”์ง€ ์•Œ๋ ค์ค˜์•ผ ๊ณ ์น  ์ˆ˜ ์žˆ๊ฒ ์ฃ ?

 

๋ฐ”๋กœ ์ž…๋ ฅ์ฐฝ ์•„๋ž˜์— ๊ฒฝ๊ณ  ๊ธ€์”จ๋กœ ์–ด๋–ค ๊ทœ์น™์„ ์ค€์ˆ˜ํ•ด์•ผ ํ•˜๋Š”์ง€ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์„ ๊ตฌํ˜„ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

register.component.html

 

๋จผ์ € ์ด๋ฉ”์ผ ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๋ถ€ํ„ฐ ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค.

 

mat-error๋Š” ๋จธํ„ฐ๋ฆฌ์–ผ ๋ชจ๋“ˆ์—์„œ ์ œ๊ณตํ•˜๋Š” ์—๋Ÿฌ ํ‘œ์‹œ ์ปดํฌ๋„ŒํŠธ ์ž…๋‹ˆ๋‹ค.

 

๊ทธ ๋‹ค์Œ์œผ๋กœ *ngIf๋Š” html์—์„œ if๋ฌธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฑด๋ฐ์š”.

 

์—ฌ๊ธฐ์„œ registerForm์˜ controls(ํผ์—์„œ ๊ตฌํ˜„ํ•œ ํ”„๋กœํผํ‹ฐ๋“ค) ์ค‘ email์ธ ์ด๋ฆ„์„ ๊ฐ€์ง„ ๊ฒƒ์— ์—๋Ÿฌ๊ฐ€ ์žˆ๋Š”์ง€ ์œ ๋ฌด๋ฅผ ํŒŒ์•…ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

required ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๋ฉด ์ž…๋ ฅํ•˜์ง€ ์•Š์€ ๊ฒƒ์ด๊ณ , required๊ฐ€ ์ •์ƒ์ด๋ผ๋ฉด ์ด๋ฉ”์ผ ํ˜•์‹์„ ๋งž์ถ”์ง€ ์•Š์€ ๊ฒƒ์ด๋ฏ€๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด ์—๋Ÿฌ ๋ฉ”์„ธ์ง€๋ฅผ ๋„์›Œ์ค๋‹ˆ๋‹ค.

 

          <input matInput formControlName="email" />
          <mat-error *ngIf="registerForm.controls['email'].invalid">
            {{
                registerForm.controls["email"].hasError("required")
                ? "์ด๋ฉ”์ผ์€ ๋นˆ์นธ์œผ๋กœ ๋‘๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹คใ…œ"
                : "์ด๋ฉ”์ผ ํ˜•์‹์— ๋งž๊ฒŒ ์ ์–ด์ฃผ์„ธ์š”ใ…œ"
            }}
          </mat-error>

 

ํŒจ์Šค์›Œ๋“œ๋„ ๋™์ผํ•˜๊ฒŒ ์ž‘์„ฑํ•ด ์ค๋‹ˆ๋‹ค.

 

input ์ž…๋ ฅ์ฐฝ ๋ฐ”๋กœ ์•„๋ž˜์— ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ฃผ์„ธ์š”.

 

          <input type="password" matInput formControlName="password" />
          <mat-error *ngIf="registerForm.controls['password'].invalid">
            {{
                registerForm.controls["password"].hasError("required")
                ? "๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ๋นˆ์นธ์œผ๋กœ ๋‘๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค ใ…œ"
                : "์ตœ์†Œ 6๊ธ€์ž ์ด์ƒ ์ž…๋ ฅํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค ใ…œ"
            }}
          </mat-error>

 

์•„๋ž˜์™€ ๊ฐ™์ด ์—๋Ÿฌ ๋ฉ”์„ธ์ง€๊ฐ€ ๋œจ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 


์˜ค๋Š˜์€ ์ด๋ ‡๊ฒŒ ํšŒ์›๊ฐ€์ž… ์ž…๋ ฅ ํ˜•์‹์— ๋งž๊ฒŒ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ,์ž…๋ ฅ์ฐฝ,๋ฒ„ํŠผ,๊ฒฝ๊ณ  ๊ธ€์”จ ๋“ฑ์„ ๋‹ค๋ค„๋ณด์•˜๋Š”๋ฐ์š”.

 

ํ˜น์‹œ๋ผ๋„ ํ‹€๋ฆฐ ์ ์ด ์žˆ๊ฑฐ๋‚˜ ๊ถ๊ธˆํ•˜์‹  ์ ์ด ์žˆ๋‹ค๋ฉด ์–ธ์ œ๋“  ๋Œ“๊ธ€๋กœ ์•Œ๋ ค์ฃผ์„ธ์š”!

728x90
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€