Signal Forms 자동 상태 클래스가 추가되었습니다 (그리고 더 많은 기능)

발행: (2025년 12월 5일 오후 05:00 GMT+9)
4 min read
원문: Dev.to

Source: Dev.to

이 Signal Form이 어떻게 구성되는지 살펴보자

Styles

컴포넌트의 SCSS는 여전히 기존 ng- 클래스를 대상으로 합니다:

input {
  /* touched vs untouched */
  &.ng-untouched {
    background-color: rgba(white, 0.05);
  }

  &.ng-touched {
    background-color: rgba(#007bff, 0.15);
  }

  /* dirty vs pristine */
  &.ng-dirty {
    box-shadow: 0 0 0 2px rgba(#007bff, 0.12);
  }

  /* valid vs invalid */
  &.ng-touched.ng-invalid {
    border-color: #e53935;
  }

  &.ng-touched.ng-valid {
    border-color: #43a047;
  }

  /* pending */
  &.ng-pending {
    border-color: orange;
  }
}

Template Walkthrough: The New [field] Directive

[field] 디렉티브는 입력을 Signal Form의 Field 객체에 직접 바인딩하여 value, touched, dirty, valid, pending 신호를 노출합니다.

디버그 패널에서 실시간 상태를 확인할 수 있습니다:

@let username = form.username();

Field State

touched: {{ username.touched() }}
dirty: {{ username.dirty() }}
valid: {{ username.valid() }}
pending: {{ username.pending() }}

기존 클래스를 수동으로 추가할 수도 있지만 번거롭습니다.

TypeScript Deep Dive: Model and form()

import { signal, form } from '@angular/forms/signals';
import { required, minLength } from '@angular/forms';

interface SignUpForm {
  username: string;
}

// Writable signal that holds the form’s data
protected model = signal({
  username: '',
});

// Connect the model to the Signal Form API
protected form = form(this.model, s => {
  s.username(required(), minLength(3));
});
  • model은 폼 데이터의 진실된 소스를 나타내는 writable signal입니다.
  • form(this.model, …)Signal Form 인스턴스를 생성하여 모델을 검증 로직에 연결합니다. s.username 빌더를 통해 required()minLength() 같은 검증기를 붙일 수 있습니다.

Restoring Automatic ng-* Classes (and Customizing Them)

Angular 21은 Signal Forms용 provideStateClasses 설정을 도입했습니다. 컴포넌트의 providers 배열(또는 전역) 에 추가하면 프레임워크가 각 필드의 신호에 따라 기존 ng- 클래스를 자동으로 적용합니다.

import { Component } from '@angular/core';
import { provideStateClasses } from '@angular/forms';

@Component({
  selector: 'app-signup',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.scss'],
  providers: [provideStateClasses()] // <-- enables automatic ng-* classes
})
export class FormComponent {
  // model and form definitions as shown above
}

Custom Class Prefixes

다른 네이밍 방식을 원한다면 provideStateClasses에 옵션 객체를 전달할 수 있습니다:

providers: [
  provideStateClasses({
    prefix: 'sf-', // e.g., sf-touched, sf-dirty, …
    map: {
      touched: 'my-touched',
      dirty: 'my-dirty',
      valid: 'my-valid',
      invalid: 'my-invalid',
      pending: 'my-pending'
    }
  })
]
  • prefix는 생성되는 모든 클래스에 사용자 정의 접두사를 추가합니다.
  • map은 개별 상태 클래스의 이름을 바꿀 수 있게 해줍니다.

이 설정을 사용하면 기존 SCSS를 새로운 클래스 이름에 맞게 수정하거나, 기본 ng- 접두사를 그대로 사용해 원래 선택자를 유지할 수 있습니다.

Summary

  • Reactive Forms에서는 ng-* 상태 클래스가 자동으로 적용됐지만, Signal Forms는 처음에 이를 생략했습니다.
  • Angular 21.0.1은 provideStateClasses를 통해 자동 클래스 생성을 다시 도입했습니다.
  • 이 프로바이더는 기본 ng- 접두사와 함께 바로 동작하거나, 접두사와 명시적 매핑을 통해 커스터마이징할 수 있습니다.
  • 각 컨트롤에 클래스를 수동으로 바인딩할 필요가 없으며, Angular가 이를 처리해 기존 스타일이 Signal Forms로 마이그레이션한 뒤에도 그대로 작동합니다.
Back to Blog

관련 글

더 보기 »

🧱 강의 9B : 제품 관리 (Angular)

소개 이 모듈은 전체 제품 관리 기능을 구축하는 데 중점을 두며, 전체 CRUD 작업과 프론트엔드와의 원활한 통합을 포함합니다.