0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CoffeeScript でフォームのバリデーションを作ってみる!

Last updated at Posted at 2025-02-20

📝 はじめに

フォームのバリデーション、面倒ですよね?
JavaScript の if 文で1つずつチェックしていると、コードが増えて管理が大変になります。
そこで、 CoffeeScript で「簡単にバリデーションできるクラス」 を作ってみました!

特徴

  • 必須入力、文字数制限、数値範囲、正規表現、メール・日付チェック などの一般的なルールを実装
  • カスタムバリデーション を追加可能
  • 英語 / 日本語のエラーメッセージ対応(カスタムメッセージもOK)
  • 1つのフィールド or 全体のフォームを一括チェック可能

🎯 バリデーション仕様

共通ルール

ルール名 内容
required 必須入力(text, select, radio)
maxLength 最大文字数
minLength 最小文字数
rangeLength 文字数の範囲(例: rangeLength: [3, 10]
min 最小値(数値)
max 最大値(数値)
between 指定範囲の数値(例: between: [10, 100]
pattern 正規表現チェック
equalsTo 他の入力値と一致するか(例: パスワード確認)

🎯 特定の入力タイプ向けバリデーション

ルール名 内容
email メールアドレス形式 (xxx@yyy.zzz)
date 日付形式 (YYYY/MM/DD)
alphaNumeric 英数字のみ
alpha 英字のみ
numeric 数字のみ
checkboxMin チェックボックスの最低選択数
checkboxMax チェックボックスの最大選択数

🎯 カスタムバリデーション対応

好きなルールを追加できます!
例えば「A で始まる文字列のみ許可する」バリデーションを作成 👇

customValidators =
  startsWithA: (value, ruleValue) ->
    if ruleValue and not value.startsWith("A")
      return { valid: false, message: "Value must start with 'A'.\n'A' で始まる必要があります。" }
    return { valid: true }

🚀 実装(CoffeeScript)

window.validation クラス を作成し、
指定のルールに基づいてフィールドをチェックします!

📌 validate(fieldName, value, rules)

1つのフィールドをバリデーション

result = validator.validate("username", "abc", { required: true, minLength: 5 })
console.log result 
# { valid: false, errors: ["[username] must be at least 5 characters.\n[username] は最小 5 文字です。"] }

📌 validateAll(fields)

複数のフィールドをまとめてバリデーション

fields = 
  username: { value: "abc", rules: { required: true, minLength: 5 } }
  email: { value: "test@example.com", rules: { email: true } }

resultAll = validator.validateAll(fields)
console.log resultAll

📜 バリデーションクラスのコード

window.validation = class Validation
  ###*
  * バリデーションエラーメッセージ
  ###
  messages:
    required: "[{field}] is required.\n[{field}] は必須です。"
    maxLength: "[{field}] must be at most {ruleValue} characters.\n[{field}] は最大 {ruleValue} 文字です。"
    minLength: "[{field}] must be at least {ruleValue} characters.\n[{field}] は最小 {ruleValue} 文字です。"
    rangeLength: "[{field}] must be between {min} and {max} characters.\n[{field}] は {min} から {max} 文字の範囲です。"
    min: "[{field}] must be at least {ruleValue}.\n[{field}] は {ruleValue} 以上である必要があります。"
    max: "[{field}] must be at most {ruleValue}.\n[{field}] は {ruleValue} 以下である必要があります。"
    between: "[{field}] must be between {min} and {max}.\n[{field}] は {min} から {max} の範囲です。"
    pattern: "[{field}] is invalid format.\n[{field}] の形式が正しくありません。"
    equalsTo: "[{field}] must be the same as {target}.\n[{field}] は {target} と一致する必要があります。"
    email: "[{field}] must be a valid email address.\n[{field}] は有効なメールアドレスである必要があります。"
    date: "[{field}] must be a valid date (YYYY/MM/DD).\n[{field}] は有効な日付形式 (YYYY/MM/DD) である必要があります。"
    alphaNumeric: "[{field}] must be alphanumeric.\n[{field}] は英数字のみです。"
    alpha: "[{field}] must contain only letters.\n[{field}] は英字のみです。"
    numeric: "[{field}] must contain only numbers.\n[{field}] は数字のみです。"
    checkboxMin: "[{field}] must select at least {ruleValue} options.\n[{field}] は最低 {ruleValue} 個選択する必要があります。"
    checkboxMax: "[{field}] must select at most {ruleValue} options.\n[{field}] は最大 {ruleValue} 個まで選択できます。"

  ###*
  * カスタムバリデーションの定義
  ###
  customValidators: {}

  ###*
  * バリデーション実行
  * @param {string} fieldName - フィールド名
  * @param {string|Array} value - 入力値
  * @param {Object} rules - バリデーションルール
  * @return {Object} - `{ valid, errors }`
  ###
  validate: (fieldName, value, rules) ->
    errors = []

    # ルール適用
    for rule, ruleValue of rules
      switch rule
        when "required"
          if not value or (Array.isArray(value) and value.length is 0)
            errors.push(@formatMessage("required", fieldName))

        when "maxLength"
          if value.length > ruleValue
            errors.push(@formatMessage("maxLength", fieldName, { ruleValue }))

        when "minLength"
          if value.length < ruleValue
            errors.push(@formatMessage("minLength", fieldName, { ruleValue }))

        when "rangeLength"
          if value.length < ruleValue[0] or value.length > ruleValue[1]
            errors.push(@formatMessage("rangeLength", fieldName, { min: ruleValue[0], max: ruleValue[1] }))

        when "min"
          if parseFloat(value) < parseFloat(ruleValue)
            errors.push(@formatMessage("min", fieldName, { ruleValue }))

        when "max"
          if parseFloat(value) > parseFloat(ruleValue)
            errors.push(@formatMessage("max", fieldName, { ruleValue }))

        when "between"
          if parseFloat(value) < parseFloat(ruleValue[0]) or parseFloat(value) > parseFloat(ruleValue[1])
            errors.push(@formatMessage("between", fieldName, { min: ruleValue[0], max: ruleValue[1] }))

        when "pattern"
          if not ruleValue.test(value)
            errors.push(@formatMessage("pattern", fieldName))

        when "equalsTo"
          if value isnt document.querySelector("[name='#{ruleValue}']").value
            errors.push(@formatMessage("equalsTo", fieldName, { target: ruleValue }))

        when "email"
          if not /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
            errors.push(@formatMessage("email", fieldName))

        when "date"
          if not /^\d{4}\/\d{2}\/\d{2}$/.test(value)
            errors.push(@formatMessage("date", fieldName))

        when "alphaNumeric"
          if not /^[a-zA-Z0-9]+$/.test(value)
            errors.push(@formatMessage("alphaNumeric", fieldName))

        when "alpha"
          if not /^[a-zA-Z]+$/.test(value)
            errors.push(@formatMessage("alpha", fieldName))

        when "numeric"
          if not /^\d+$/.test(value)
            errors.push(@formatMessage("numeric", fieldName))

        when "checkboxMin"
          if value.length < ruleValue
            errors.push(@formatMessage("checkboxMin", fieldName, { ruleValue }))

        when "checkboxMax"
          if value.length > ruleValue
            errors.push(@formatMessage("checkboxMax", fieldName, { ruleValue }))

      # カスタムバリデーション
      if rule of @customValidators
        result = @customValidators[rule](value, ruleValue)
        unless result.valid
          errors.push(result.message)

    return { valid: errors.length is 0, errors }

  ###*
  * 複数のフィールドをバリデーション
  * @param {Object} fields - `{ fieldName: { value, rules } }`
  * @return {Object} - `{ valid, results }`
  ###
  validateAll: (fields) ->
    results = {}
    valid = true

    for fieldName, data of fields
      result = @validate(fieldName, data.value, data.rules)
      results[fieldName] = result
      valid = false unless result.valid

    return { valid, results }

  ###*
  * メッセージフォーマット
  * @param {string} key - メッセージキー
  * @param {string} fieldName - フィールド名
  * @param {Object} [params] - 追加の置換パラメータ
  * @return {string} - フォーマット済みメッセージ
  ###
  formatMessage: (key, fieldName, params = {}) ->
    message = @messages[key].replace("{field}", fieldName)
    for param, value of params
      message = message.replace("{#{param}}", value)
    return message


🎉 まとめ

CoffeeScript で フォームバリデーションをシンプルに実装 できました!

  • バリデーションを追加するのが超簡単!
  • エラーメッセージも日本語 / 英語対応!
  • カスタムルールも拡張可能!

CoffeeScript を使う機会があるなら、ぜひ試してみてください! ✨

👉 感想やフィードバックがあれば、ぜひコメントしてください!
🚀 Qiita のストックもよろしくお願いします! 🚀

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?