前提・実現したいこと
JavaScriptを利用して、Html.TextBoxForに"1,234,567"のように3桁コンマ区切り表示したでデータを、クライアントサイドの検証にひっかからずにForm送信し、データベースのDecimal型のデータを更新できるようにしたいです。submit時にJavaScriptでコンマ無し数値に変更すればよいように思いますが、具体的なソースコードが思い浮かばず困っております。
どうぞよろしくお願いいたします。
環境
Windows10
VS2017(Visual Studio 2017 Community version 15.9.4)
(SQLServer: MSSQLLOCALDB)
Asp.Net MVC で開発
事象詳細
VSからWebアプリを実行し、Chromeにアプリが開きます。
そして、データベースに保存済の情報がブラウザに表示されます。
(データ”Price”はdecimal型でデータベースに保存されています。)
Priceのデータが3桁区切り数値(例:1,234,567)と表示されます。
Form送信するために保存ボタンを押すと、検証にひっかかり、Form送信できません。
3桁コンマ区切り表示を実現するためのJavaScriptは、下記サイトを参考に実装しました。
https://webllica.com/add-comma-as-thousands-separator/
これにより、Html.TextBoxFor で、編集時(Focus時)は"1234567"のようにコンマ無しで入力し、表示時(Blur時)は"1,234,567"のように3桁コンマ区切り表示できるようになったのですが、submitでForm送信するとクライアントサイドの検証により、「値'1,234,567'はPriceに対して無効です」とエラーになりFrom送信できません。
ソースコード
C#
1//Model: Part.cs 2using System.ComponentModel.DataAnnotations; 3using System.ComponentModel.DataAnnotations.Schema; 4 5namespace Contract.Models 6{ 7 public class Part 8 { 9 public int ID { get; set; } 10 11 [StringLength(50)] 12 public string Name { get; set; } 13 14 [Column("money")] 15 [DataType(DataType.Currency)] 16 public decimal Price { get; set; } 17 } 18}
C#
1//Model: PartContext.cs 2using System.Data.Entity; 3 4namespace Contract.Models 5{ 6 public class PartContext : DbContext 7 { 8 public PartContext() : base("PartContext") 9 { 10 } 11 public DbSet<Part> Parts { get; set; } 12 } 13}
C#
1//App_Start: BundleCOnfig.cs 2using System.Web.Optimization; 3 4namespace Contract 5{ 6 public class BundleConfig 7 { 8 public static void RegisterBundles(BundleCollection bundles) 9 { 10 bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 11 "~/Scripts/jquery-{version}.js")); 12 13 bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 14 "~/Scripts/jquery.validate*")); 15 16 bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 17 "~/Scripts/modernizr-*")); 18 } 19 } 20}
C#
1//Controllers: PartController.cs 2using Contract.Models; 3using System.Data.Entity; 4using System.Linq; 5using System.Net; 6using System.Web.Mvc; 7 8namespace Contract.Controllers 9{ 10 public class PartController : Controller 11 { 12 private PartContext db = new PartContext(); 13 14 // GET: Part 15 public ActionResult Index() 16 { 17 return View(db.Parts.ToList()); 18 } 19 20 21 // GET: Part/Edit/5 22 public ActionResult Edit(int? id) 23 { 24 if (id == null) 25 { 26 return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 27 } 28 Part part = db.Parts.Find(id); 29 if (part == null) 30 { 31 return HttpNotFound(); 32 } 33 return View(part); 34 } 35 36 // POST: Part/Edit/5 37 [HttpPost] 38 [ValidateAntiForgeryToken] 39 public ActionResult Edit([Bind(Include = "ID,Name,Price")] Part part) 40 { 41 if (ModelState.IsValid) 42 { 43 db.Entry(part).State = EntityState.Modified; 44 db.SaveChanges(); 45 return RedirectToAction("Index"); 46 } 47 return View(part); 48 } 49 50 protected override void Dispose(bool disposing) 51 { 52 if (disposing) 53 { 54 db.Dispose(); 55 } 56 base.Dispose(disposing); 57 } 58 } 59}
C#
1//View:Shared: _Layout.cshtml 2<!DOCTYPE html> 3<html> 4<head> 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 6 <meta charset="utf-8" /> 7 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 8 @Styles.Render("~/Content/css") 9 @Scripts.Render("~/bundles/modernizr") 10</head> 11<body> 12 <div class="container body-content"> 13 @RenderBody() 14 </div> 15 16 @Scripts.Render("~/bundles/jquery") 17 @Scripts.Render("~/bundles/bootstrap") 18 @Scripts.Render("~/bundles/jqueryval") 19 @RenderSection("scripts", required: false) 20 <script src="~/Scripts/myScript.js?timestamp=@DateTime.Now.Ticks.ToString()"></script> 21</body> 22</html>
C#
1//View: Index.cshtml 2@model IEnumerable<Contract.Models.Part> 3<table class="table"> 4 <tr> 5 <th>@Html.DisplayNameFor(model => model.Name)</th> 6 <th>@Html.DisplayNameFor(model => model.Price)</th> 7 </tr> 8 9 @foreach (var item in Model) 10 { 11 <tr> 12 <td>@Html.DisplayFor(modelItem => item.Name)</td> 13 <td>@Html.DisplayFor(modelItem => item.Price)</td> 14 <td>@Html.ActionLink("Edit", "Edit", new { id = item.ID })</td> 15 </tr> 16 } 17</table>
C#
1//View:Edit.cshtml 2@model Contract.Models.Part 3@using (Html.BeginForm()) 4{ 5 @Html.AntiForgeryToken() 6 @Html.ValidationSummary(true) 7 8 <div class="form-horizontal"> 9 @Html.HiddenFor(model => model.ID) 10 11 <div class="form-group"> 12 Name 13 <div> 14 @Html.EditorFor(model => model.Name) 15 @Html.ValidationMessageFor(model => model.Name, "") 16 </div> 17 Price 18 <div> 19 @Html.EditorFor(model => model.Price, "{0:F0}") 20 @Html.ValidationMessageFor(model => model.Price, "数値にしてください", new { @class = "text-danger" }) 21 </div> 22 </div> 23 24 <div class="form-group"> 25 <div> 26 <input type="submit" value="保存" formmethod="post"/> 27 </div> 28 </div> 29 </div> 30}
JavaScript
1//出典: https://webllica.com/add-comma-as-thousands-separator/ 2//**** 画面表示完了後に、契約金額の表示をコンマ区切りとする **** 3window.onload = function () { 4 elm.value = addFigure(document.getElementById("Price").value); 5}; 6 7// * 数値の3桁カンマ区切り 8// * 入力値をカンマ区切りにして返却 9// * [引数] numVal: 入力数値 10// * [返却値] String(): カンマ区切りされた文字列 11// */ 12function addFigure(numVal) { 13 // 空の場合そのまま返却 14 if (numVal === '') { 15 return ''; 16 } 17 // 全角から半角へ変換し、既にカンマが入力されていたら事前に削除 18 numVal = toHalfWidth(numVal).replace(/,/g, "").trim(); 19 // 数値でなければそのまま返却 20 if (!/^[+|-]?(\d*)(.\d+)?$/.test(numVal)) { 21 return numVal; 22 } 23 // 整数部分と小数部分に分割 24 var numData = numVal.toString().split('.'); 25 // 整数部分を3桁カンマ区切りへ 26 numData[0] = Number(numData[0]).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); 27 // 小数部分と結合して返却 28 return numData.join('.'); 29} 30 31///** 32// * カンマ外し 33// * 入力値のカンマを取り除いて返却 34// * [引数] strVal: 半角でカンマ区切りされた数値 35// * [返却値] String(): カンマを削除した数値 36// */ 37function delFigure(strVal) { 38 return strVal.replace(/,/g, ""); 39} 40 41///** 42// * 全角から半角への変換関数 43// * 入力値の英数記号を半角変換して返却 44// * [引数] strVal: 入力値 45// * [返却値] String(): 半角変換された文字列 46// */ 47function toHalfWidth(strVal) { 48 // 半角変換 49 var halfVal = strVal.replace(/[!-~]/g, 50 function (tmpStr) { 51 // 文字コードをシフト 52 return String.fromCharCode(tmpStr.charCodeAt(0) - 0xFEE0); 53 }); 54 return halfVal; 55} 56 57///** 58// * 処理を適用するテキストボックスへのイベント設定 59// * Blur : カンマ区切り処理実施 60// * Focus : カンマ削除処理実施 61// */ 62var elm = document.getElementById('Price'); 63 64elm.addEventListener('blur', 65 function () { 66 this.value = addFigure(this.value); 67 }, false); 68 69elm.addEventListener('focus', 70 function () { 71 this.value = delFigure(this.value); 72 }, false);
回答2件
あなたの回答
tips
プレビュー