質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.38%

  • C#

    9489questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • ASP.NET

    636questions

    ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

  • MVC

    270questions

    MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

TextBoxFor メソッドでmm:ssのフォーマットを指定したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 93

asr1919

score 6

前提・実現したいこと

TextBoxFor メソッドで、
mm:ss
分と秒のフォーマットを指定したいですが可能でしょうか。

環境:
windows10 pro
MVC5

試したこと

色んなサイトを参照し、以下のようにフォーマットを試しました。

            [Display(Name = "時間")]
            [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = @"{0:mm\:ss}")]
            public TimeSpan? TimeFrom { get; set; }
            <div>
               @Html.TextBoxFor(m => m.TimeFrom, "{0:mm\\:ss}", new { placeholder = "00:00" })
            </div>

            <div>
               @Html.ValidationMessageFor(m => m.TimeFrom, "", new { @class = "text-danger" })
            </div>


これでこのテキストボックスに例えば、
30:00
と入力後にclickイベント等を発火すると、ValidationMessageForで

'30:00' は 時間 に対して無効です。


が表示されます。

しかし、
23:59
など24:00を超えない値はエラーが表示されません。

これを解決することはできますでしょうか。
よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • SurferOnWww

    2019/07/12 19:29 編集

    質問者さんの言うフォーマットの指定(TextBoxFor の第 2 引数に "{0:mm\\:ss}" を設定)はあくまでブラウザ上での表示だけの話。エラーはテキストボックスの値をブラウザからサーバーに送信した時にサーバーで受け取った値が有効か否かを判定した結果です。その 2 つを混同しているようですが、全く違うものと認識してください。

    フォーマットを指定してテキストボックス上の表示が期待通りできたからと言って、それはあくまでブラウザ上の表示だけの話であって、ポストされた値のサーバー側での解釈は関係ないです。12:34 という文字列がブラウザから送信されてきたら、サーバーは 12 時間 23 分と解釈します(12 分 34 秒ではありません)。

    キャンセル

  • asr1919

    2019/07/16 08:54

    ありがとうございます。
    確かにサーバー側ではhh:mmになってるので、受け取った値に対してmm:ssにするよう
    変えてあげないといけないですね。

    キャンセル

  • SurferOnWww

    2019/07/16 09:08 編集

    「受け取った」というのはどの時点のことを言ってますか?

    例えば、前にやったように 30:00 とブラウザに表示されたテキストボックスに入力して送信ボタンをクリックしたときは、アクションメソッドで受けとる前にサーバー側のどこかの処理で hh:mm と判断されてエラーになったのですよ。

    「変えてあげる」機会はないです。なので、回答に書いたように hh:mm:ss 形式で入力する他ないです。

    理解してないようです。

    キャンセル

回答 1

checkベストアンサー

0

30:00 でエラーが出たのは 30 時 00 分と解釈されたからだと思います。(TimeSpan 値は、[-]d.hh:mm:ss.ff で表され、hh は 24 時間制の時間となりますが、それに 30 と入力されたのでエラーになった)

00 分 00 秒以上、59 分 59 秒以下という範囲を超えたらエラーを出すにはデータアノテーション属性(RegularExpression または Range)を付与することで可能です。

あと、未検証ですが、00:mm:ss という形でテキストボックスに入力する必要がありそうです。

【追記】

ちょっと検証してみました。

テキストボックスの表示は mm:ss としても、それを送信してサーバー側で受けるときは hh:mm と解釈されるのが問題です。

つまり、例えば、テキストボックスに 30:00 とか 59:59 とか mm:ss 形式であれば有効な数字を入力しても、サーバー側では hh:mm 形式と解釈され、30 とか 59 は hh としては不正なのでモデルバインディングできずエラーになります。

なので、TextBoxFor の第 2 引数に "{0:mm\\:ss}" を設定するのは mm:ss 形式で表示するだけならいいかもしれませんが、その後ユーザーが編集して送信ということが必要なら、送信する前に 00:mm:ss にしなければならないということで、操作が面倒になるだけなので意味がなさそうです。

TextBoxFor の第 2 引数は "{0:hh\\:mm\\:ss}" と設定しで最初から hh:mm:ss 形式で表示し、00 分 00 秒以上、59 分 59 秒以下という範囲を超えたらエラーを出すにはデータアノテーション属性(RegularExpression または Range)を付与することで対応するのをお勧めします。

ご参考までに検証に使ったコードをアップしておきます。

Model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Globalization;

namespace Mvc5App.Models
{
    public class TimeSpanModel
    {
        [Required]
        // クライアント側の検証を無効にすれば RangeAttribute でも可
        //[Range(typeof(TimeSpan), "00:00:00", "00:59:59")]
        [RegularExpression(@"^00:[0-5]\d:[0-5]\d$")]
        public TimeSpan Start { set; get; }

        [Required]
        // クライアント側の検証を無効にすれば RangeAttribute でも可
        //[Range(typeof(TimeSpan), "00:00:00", "00:59:59")]
        [RegularExpression(@"^00:[0-5]\d:[0-5]\d$")]
        public TimeSpan Stop { set; get; }
    }
}

View

@model Mvc5App.Models.TimeSpanModel

@{
    ViewBag.Title = "TimeSpanTest";
    Layout = "~/Views/Shared/_Layout.cshtml";

    // クライアント側での検証を無効にするには以下のコメントアウトを解除
    //Html.EnableClientValidation(false);
}

<h2>TimeSpanTest</h2>

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>TimeSpanModel</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Start, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Start, "{0:hh\\:mm\\:ss}", new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Start, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Stop, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Stop, "{0:hh\\:mm\\:ss}", new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Stop, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Controller

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
using Mvc5App.Models;
using System.IO;

namespace Mvc5App.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult TimeSpanTest()
        {
            TimeSpanModel model = new TimeSpanModel
            {
                Start = new TimeSpan(0, 0, 0),
                Stop = new TimeSpan(0, 59, 59)
            };

            return View(model);
        }

        [HttpPost]
        public ActionResult TimeSpanTest(TimeSpanModel model)
        {
            if (ModelState.IsValid)
            {
                return RedirectToAction("Index");
            }

            return View(model);
        }
    }
}

Model に付与した Rquired と RegularExpression での検証結果は以下のようになります。下の例ではエラーメッセージはデフォルトですが自由に設定できます。

イメージ説明

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.38%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • C#

    9489questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • ASP.NET

    636questions

    ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

  • MVC

    270questions

    MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。