前提・実現したいこと
TypeScript + Knockout.JSにおいて、サーバから取得したListをdata-bind=foreachで展開し、foreach内のclickにメソッドをbindしたい
現在、Knockout.JSが使われたJavaScirptをTypeScriptに置き換え、関数をクラス化する作業を行っております。
元のソースの中で、サーバから取得したResultListをmapping.fromJSによりbindし、foreachで展開している箇所があるのですが、元のJavaScirptの関数をクラス化してbindしようとした際、クラス内のメソッドを参照することができず、エラーが発生してしまっております。
正しく展開する方法を教えていただけないでしょうか。
発生している問題・エラーメッセージ
Uncaught Reference Error: Unable to process binding "foreach: function(){return hogeList}" Message: Unable to process binding "click: function(){return hoge} Message hoge is not defined
該当のソースコード
html
1***略*** 2<tbody data-bind="foreach: ResultList"> 3 <tr data-bind="css:{'tile-active':ActiveFlag() == 1}"> 4 <th class="tile-split" data-bind="attr:{'rowspan': Rowspan()}"> 5 <div class="text-center" data-bind="text:Day()"></div> 6 </th> 7 <td class="col-fit" data-bind="css:{'tile-split':BorderLineFlag() == 1}"> 8 <div class="tile-wrapper"> 9 <div class="stole-wrapper" data-bind="foreach:hogeList"> 10 <div class="stole-inner" dat-bind="css:{bibView:PriorityIsViewFlag() == 1},click:hoge"> 11 </div> 12 </div> 13 </td> 14</tbody> 15***略***
■元ソース
javascript
1***略*** 2 3hoge = function () { 4 var self = this; 5 6 bootbox.confirm('実行しますか?', function (r) { 7 if (r) { 8 $.ajax({ 9 type: "post", 10 url: url, 11 data: { 12 ID: self.ID(), 13 flag: 1 14 }, 15 cache: false, 16 dataType: "json", 17 }).done(function (result) { 18 if (!result.Result) { 19 bootbox.alert(result.Message); 20 } else { 21 self.Status(-1); 22 23 try { 24 viewModel.keepList.ID(null); 25 ***略*** 26 } finally { } 27 28 listUpdate(); 29 get(); 30 } 31 }); 32 } 33 } 34} 35 36***略*** 37 38$(function () { 39 viewModel = {}; 40 41 $.ajax({ 42 type: "post", 43 url: url, 44 cache: false, 45 dataType: "json" 46 }).done(function (result) { 47 viewModel = ko.mapping.fromJS(result); 48 ko.applyBindings(viewModel); 49 ***略*** 50 }) 51 ***略*** 52)}; 53
■修正後ソース
typescript
1***略*** 2class hogeClass { 3***略*** 4 hoge(): void { 5 let self = this; 6 7 bootbox.confirm('実行しますか?', function (r) { 8 if (r) { 9 $.ajax({ 10 type: "post", 11 url: url, 12 data: { 13 ID: self.ID(), 14 flag: 1 15 }, 16 cache: false, 17 dataType: "json", 18 }).done(function (result) { 19 if (!result.Result) { 20 bootbox.alert(result.Message); 21 } else { 22 self.Status(-1); 23 24 try { 25 viewModel.keepList.ID(null); 26 ***略*** 27 } finally { } 28 29 listUpdate(); 30 get(); 31 } 32 }); 33 } 34 } 35 } 36} 37 38***略*** 39 40$(function () { 41 let viewModel = {}; 42 43 $.ajax({ 44 type: "post", 45 url: url, 46 cache: false, 47 dataType: "json" 48 }).done(function (result) { 49 viewModel = ko.mapping.fromJS(result, {}, new hogeClass()); 50 ko.applyBindings(viewModel); 51 ***略*** 52 }) 53 ***略*** 54)}; 55
json
1{ 2 ResultList: [ 3 ActiveFlag: 0, 4 BorderLineFlag: 1, 5 Day: "2021/10/20", 6 hogeList:[ 7 ***略*** 8 ID: xxxx, 9 ***略*** 10 ] 11 ***略*** 12 ] 13}
試したこと
・viewModelをmappingする際の順序の変更などは試しました。
・先にhogeClassだけをapplyBindingsし、後からmapping.fromJSでresultを追加する方法を試しました
・ko.mapping.fromJS(ko.mapping.fromJS(result), {}, new hogeClass());とし、resultを先にマッピングすることを試しました
また、hogeメソッドを「public hoge: () => void;」として先に定義し、constructorで中身を実装するなどもしてみました
使用環境・ツールなど
Visual Studio 4.8.04084
typescript 3.9.10
jquery: 3.6.0
knockout: 3.5.1
knockout.mapping: 2.4.0
webpack: 5.44.0
ASP.NET MVC 5
TypeScript compileOptions
target: ES2020
module: ESNext
あなたの回答
tips
プレビュー