ASP.NET MVC5 KnockoutJS 映射“未捕获的类型错误:无法读取未定义的属性 'fromJS'”错误

Posted

技术标签:

【中文标题】ASP.NET MVC5 KnockoutJS 映射“未捕获的类型错误:无法读取未定义的属性 \'fromJS\'”错误【英文标题】:ASP.NET MVC5 KnockoutJS mapping "Uncaught TypeError: Cannot read property 'fromJS' of undefined" errorASP.NET MVC5 KnockoutJS 映射“未捕获的类型错误:无法读取未定义的属性 'fromJS'”错误 【发布时间】:2019-01-19 09:33:30 【问题描述】:

寻求有关 KnockoutJS 和我正在开发的 MVC 应用程序的帮助。

我正在尝试使用 Knockoutjs 将服务器端视图模型映射到客户端视图模型,然后通过视图将每个客户端视图模型添加到集合中,然后(不在下面的代码中)使用 AJAX 返回到控制器。

到目前为止,当我尝试将视图模型添加到剔除数组时,我收到以下错误:

TrainingCourse.js:47 Uncaught TypeError: Cannot read property 'fromJS' of undefined

我的淘汰脚本如下:

TrainingCourseViewModel = function(data) 
    var self = this;
    jsonData = data;
        self.rows = ko.observableArray([
        new TrainingCourseItemViewModel(
            "TrainLevel": 1, "TrainCourseTitle": null, "TrainProviderName": null, "TrainDateStarted": null,
                "TrainDateCompleted": null, "TrainHoursAttended": 0, "TrainCost": 0, "QualificationGained": false,
                "VoluntDateStarted": null, "VoluntDateEnded": null, "VoluntWhoWith": null, "VoluntHoursAttended": 0, "VoluntContactDetails": null,
                "WorkExpDateStarted": null, "WorkExpDateEnded": null, "WorkExpWhoWith": null, "WorkExpHoursAttended": 0, "WorkExpContactDetailsEmployer": null,
            "DateofPurchase": null, "Cost": 0, "PurchaseDetails": null, "PersonId": 0
        )
    ]);

    self.addRow = function () 
        self.rows.push(new TrainingCourseItemViewModel(
            "TrainLevel": 0, "TrainCourseTitle": null, "TrainProviderName": null, "TrainDateStarted": null,
            "TrainDateCompleted": null, "TrainHoursAttended": 0, "TrainCost": 0, "QualificationGained": false,
            "VoluntDateStarted": null, "VoluntDateEnded": null, "VoluntWhoWith": null, "VoluntHoursAttended": 0, "VoluntContactDetails": null,
            "WorkExpDateStarted": null, "WorkExpDateEnded": null, "WorkExpWhoWith": null, "WorkExpHoursAttended": 0, "WorkExpContactDetailsEmployer": null,
            "DateofPurchase": null, "Cost": 0, "PurchaseDetails": null, "PersonId": 0));
    

    self.removeRow = function (row) 
        self.rows.remove(row);
        calculateTrainingCost();
        calculateOverallTotal();
        trainingDateAutoCompleted();
    

    function TrainingCourseItemViewModel() 
        var self = this;
        ko.mapping.fromJS(data, , self);
        


错误发生在该文件的第 47 行,如下所示:

function TrainingCourseItemViewModel() 
        var self = this;
        ko.mapping.fromJS(data, , self);
        

相关视图如下:

@* Serialize model in to JSON *@
@ string data = new javascriptSerializer().Serialize(Model);



<h3>Add Training/Qualification</h3>
<div id="TrainingCourseViewModel">
    <table class="table table-hover">

        <thead>
            <tr>
                <th>CQFW Level</th>
                <th>Course Title</th>
                <th>Provider Name</th>
                <th>Date Started</th>
                <th>Date Completed</th>
                <th>Hours Attended</th>
                <th>Cost</th>
                <th>Qualification Gained?</th>
            </tr>
        </thead>

            <tbody data-bind="foreach: rows" id="trainingPadding">
                <tr>
                    <td class="col-md-1">@html.EnumDropDownListFor(modelItem => Model.TrainLevel, new  @class = "form-control site-level-ddl trainingLevel", data_bind = "value: TrainLevel" )</td>
                    <td class="col-md-2"><input type="text" data-bind="value: TrainCourseTitle" class="form-control" /></td>
                    <td class="col-md-2"><input type="text" data-bind="value: TrainProviderName" class="form-control" /></td>
                    <td class="col-md-1"><input type="text" data-bind="value: TrainDateStarted" class="form-control date-input datepicker" placeholder="dd/mm/yyyy" /></td>
                    <td class="col-md-1"><input type="text" data-bind="value: TrainDateCompleted" class="form-control date-input datepicker trainingDateCompleted hasDatepicker" onchange="trainingDateAutoCompleted()" placeholder="dd/mm/yyyy" /></td>
                    <td class="col-md-1"><input type="text" data-bind="value: TrainHoursAttended" class="form-control" onkeyup="calculateTrainingCost()" /></td>
                    <td class="col-md-1"><input type="text" data-bind="value: TrainCost" class="form-control trainingCost" placeholder="£0.00" onkeyup="calculateTrainingCost(), calculateOverallTotal()" /></td>
                    <td class="col-md-1" style="text-align: center"><input type="checkbox" data-bind="value: QualificationGained" class="" /></td>
                    <td class="col-md-1" style="width: 4%; text-align: center"><a href="#" data-bind="click: $root.removeRow" class="glyphicon glyphicon-trash text-danger" /></td>
                </tr>
            </tbody>



    </table>

    <input type="button" value="Add" data-bind="click: addRow" class="btn btn-default" />
</div>

<!---Scripts-->
<script type="text/javascript" src="~/Scripts/knockout-3.4.2.js"></script>
<script type="text/javascript" src="~/Scripts/knockout.mapping-latest.js"></script>
<script type="text/javascript" src="~/Scripts/KnockoutViewModels/TrainingCourse.js"></script>
<script type="text/javascript">
    var trainingCourseViewModel = new TrainingCourseViewModel(@Html.Raw(data));
    ko.applyBindings(trainingCourseViewModel);
</script>

任何帮助或建议将不胜感激,因为我对 KnockoutJS 还是很陌生...

干杯

【问题讨论】:

TrainingCourseItemViewModel中添加data参数:function TrainingCourseItemViewModel(data) 感谢您的建议。你能详细说明一下吗? TrainingCourseItemViewModel 中,您调用ko.mapping.fromJS(data, , self);,但data 未定义。当你调用new TrainingCourseItemViewModel( ... )时,TrainingCourseItemViewModel不会得到这个对象,因为它没有任何参数。 谢谢,尝试添加为参数,但我仍然收到相同的错误 感谢您的提琴,我在此基础上进行了一些测试... 【参考方案1】:

在创建视图模型实例并启动绑定时,确保 dom 完全加载。

如果是纯java脚本, 使用,

window.addEventListener('DOMContentLoaded', function()
    var trainingCourseViewModel = new TrainingCourseViewModel(@Html.Raw(data));
    ko.applyBindings(trainingCourseViewModel);
 );

或者,如果您使用的是 jQuery 框架,

$(function()
   var trainingCourseViewModel = new TrainingCourseViewModel(@Html.Raw(data));
    ko.applyBindings(trainingCourseViewModel);
);

【讨论】:

感谢您的建议,但不幸的是它不起作用...我现在在页面加载时收到相同的错误 将数据参数添加到函数TrainingCourseItemViewModel(jsData) var self = this; ko.mapping.fromJS(jsData, , self); 浏览器按F12,查看Knockout js和映射插件是否下载到浏览器。如果插件不在 Script 文件夹中,请通过包管理器控制台添加它。并获取子视图模型构造函数,function TrainingCourseItemViewModel(jsData) var self = this; ko.mapping.fromJS(jsData, , self); 到父视图模型构造函数的外面。 插件存在于脚本文件夹中,当子虚拟机在父虚拟机外部时出现同样的错误...... 好像映射插件没有正确加载。按 F12 看看是否加载了映射插件。

以上是关于ASP.NET MVC5 KnockoutJS 映射“未捕获的类型错误:无法读取未定义的属性 'fromJS'”错误的主要内容,如果未能解决你的问题,请参考以下文章

从 ASP.NET MVC 复杂模型创建 KnockoutJS 模型

有人愤怒地使用带有 asp.net-mvc 的 Knockoutjs 吗? [关闭]

使用 knockoutjs 绑定来自 JSON 对象的数据 - Asp.net MVC

《ASP.NET MVC 5 破境之道》:第一境 ASP.Net MVC5项目初探 — 第二节:MVC5项目结构

ASP.NET MVC5 入门

ASP.NET从MVC5升级到MVC6