2023/03/03 にある meetup app osaka@7 で話すやつです。
meetupapp.connpass.com
年末のBlazorのアドベントカレンダーでHandsontableをBlazorで使う話が書かれてたのでやってみました。若干非効率ながら全部C#で書けました!コードはそれを参考にさせてもらいました。(てかそのJSをC#に書きなおさせてもらいました)
qiita.com
@page "/" @using Blazor.DynamicJS @inject IJSRuntime jsRuntime <div @ref="_grid"></div> @code { private ElementReference _grid; classCol { publicobject? data { get; set; } publicobject? readOnly { get; set; } publicobject? width { get; set; } publicobject? className { get; set; } publicobject? type { get; set; } publicobject? numericFormat { get; set; } } publicclassProductMaster { publicstring? Edit { get; set; } publicbool Select { get; set; } publicstring? ProductCode { get; set; } publicstring? ProductName { get; set; } publicint UnitPrice { get; set; } publicstring? Comment { get; set; } } protectedoverrideasync Task OnAfterRenderAsync(bool firstRender) { if (!firstRender) return; var js =await jsRuntime.CreateDymaicRuntimeAsync(); conststring COL_EDIT ="edit"; conststring COL_SELECT ="select"; conststring COL_PRODUCTCODE ="productCode"; conststring COL_PRODUCTNAME ="productName"; conststring COL_UNITPRICE ="unitPrice"; conststring COL_COMMENT ="comment"; conststring EDIT_MARK ="*"; //コンストラクタ引数をJavaScriptの世界につくるvar arg = js.ToJS(new { data =new object[0], colHeaders =new[] { "編集", "選択", "商品CD", "商品名", "単価", "備考" }, columns =new Col[] { new Col{ data = COL_EDIT, readOnly =true, type ="text" }, new Col{ data = COL_SELECT, type ="checkbox" }, new Col{ data = COL_PRODUCTCODE, type ="text", width =80 }, new Col{ data = COL_PRODUCTNAME, type ="text", width =200, className ="htLeft htMiddle" }, new Col{ data = COL_UNITPRICE, type ="numeric", numericFormat =new { pattern ="0,00", culture ="ja-JP" } }, new Col{ data = COL_COMMENT, type ="text", width =300, className ="htLeft htMiddle" } }, enterMoves =new { row =0, col =1 }, outsideClickDeselects =true, manualColumnResize =true, fillHandle =false, }); //コールバックで使うので先に宣言dynamic? hot =null; //オブジェクトの中にシリアライズできないメンバーは入れれないので別途ここで入れる arg.afterChange = (Action<dynamic, dynamic>)((changes, source) => { if (source =="loadData") return; //これほんとは重いからやらない方がいい//changesの型を調べてシリアライズして持ってきた方がいいfor (var i =0; i < (int)changes.length; i++) { var change = changes[i]; // 編集と選択は対象外if (change[1] == COL_EDIT || change[1] == COL_SELECT) continue; // 変更前と変更後が同じは対象外if (change[2] == change[3]) continue; // 編集に"*"を付ける hot?.setDataAtCell(changes[0][0], 0, EDIT_MARK); } }); hot = js.New("Handsontable", _grid, arg); var products =new List<ProductMaster>() { { new ProductMaster() { Edit ="", Select =false, ProductCode ="S0001", ProductName ="りんご", UnitPrice =100, Comment ="青森産" } }, { new ProductMaster() { Edit ="", Select =false, ProductCode ="S0002", ProductName ="みかん", UnitPrice =80, Comment ="静岡産" } }, { new ProductMaster() { Edit ="", Select =true, ProductCode ="S0003", ProductName ="メロン", UnitPrice =1000, Comment ="袋井クラウンメロン" } } }; hot.loadData(products); } }
コールバックの中の処理がちょっと非効率。ループ回るたびにJSの世界とやり取りしてるんですよね・・・。これはchangesがシリアライズできたらいんですけどね、これ複数の型が入ってる配列だから今うまくシリアライズできないんですよねー。なんかいい方法考えよう。