【问题标题】:Load and Post models to and from Controller向控制器加载和发布模型
【发布时间】:2017-12-13 20:22:03
【问题描述】:

我正在尝试将模型从我的 Asp.Net Web API 控制器加载到我的 ViewModel 上(其中包含一个模型,其中包含列表的列表......非常复杂)。

.Net 模型是:

public class PlateTemplateExtendedDto
    {
        public int Id { get; set; }
        public string Description { get; set; }
        public decimal Height { get; set; }
        public decimal Width { get; set; }
        public List<PlateTemplateGroupDto> PlateTemplateGroups { get; set; } = new List<PlateTemplateGroupDto>();

    }

该类中的列表项声明为:

  public class PlateTemplateGroupDto
    {
        public int Id { get; set; }
        public string Description { get; set; }
        public List<PlateTemplateGroupComponentDto> Components { get; set; } = new List<PlateTemplateGroupComponentDto>();

    }

然后在那个列表中,作为一个对象:

public class PlateTemplateGroupComponentDto
    {
        public int Id { get; set; }
        public int PlateTemplateGroupId { get; set; }
        public int GroupComponentTypeId { get; set; }
        public string GroupComponentType { get; set; }
        public int EntryDisplayOrderId { get; set; }
}

这是我的一些视图模型。 “数据”是我想要保存我的数据模型并将其发回的字段。

function TemplateViewModel() {
    var self = this;

    self.Data = ko.observable();

    self.TemplateId = ko.observable($("#InputTemplateId").val());
    self.CreateMode = ko.observable(!!self.TemplateId() == false);


    self.loadData = function () {
        $.get("/api/Template/Get", { id: self.TemplateId() }).done(function (data) {
            self.Data(ko.mapping.fromJS(data));
            alert(self.Data().PlateTemplateGroups().length);
        });
    }


    self.save = function () {
        var data = ko.mapping.toJS(self.TemplateGroups);
        $.post("/api/Template/Save", data).done(function (result) {
            alert(result);
        });
    };

    if (!self.CreateMode()) {
        self.loadData();
    }

}

加载后的警报有效...如果我闯入代码,我可以看到 Data 持有我期望的模型。

但是,当我尝试在视图上使用它时,它会失败:

 <ul class="nav nav-tabs" data-bind="foreach: Data().PlateTemplateGroups()">
                <li data-bind="css: {active: $index()==0}"><a data-toggle="tab" data-bind="attr: {href: ('#tabId' + $index())}"><span data-bind="text: Description"></span></a></li>
            </ul>

什么都没有发生。这是因为某些东西还没有初始化吗?甚至有可能做到这一点吗?控制台窗口出现错误:

Uncaught TypeError: Unable to process binding "foreach: function (){return Data().PlateTemplateGroups() }" 消息:无法读取 未定义的属性“PlateTemplateGroups”

在调试器中,如果我在加载数据之后断点...我会看到:

事实上,从 api 调用加载后,我可以看到模型中的所有数据:

self.Data().PlateTemplateGroups()[0].Components()

它显示了 PlateTemplateGroups 列表中的第一项,我可以看到“组件”中的项目(这也是一个列表。这一切似乎都可以观察到,因为我将它们作为函数访问。

我的视图模型应用绑定发生在我的 js 文件的末尾:

function PlateTemplateViewModel() {
    var self = this;
....
}

$(document).ready(function () {
    ko.applyBindings(new PlateTemplateViewModel(), $("#plateTemplate")[0]);
});

【问题讨论】:

    标签: c# asp.net-mvc knockout.js


    【解决方案1】:

    浏览器控制台有错误吗?您确定 PlateTemplateGroups 是可观察字段吗?

    请在渲染前向我们展示 api 响应示例和 viewModel 状态

    function TemplateViewModel() {
        var self = this;
    
        self.Data = ko.observable({PlateTemplateGroups: ko.observableArray()});
     //....
    

    您的代码的执行计划: 致电new TemplateViewModel(), 致电self.loadData 致电applyBindings // in this moment data didn't return from the server and ko throw error, 调用 loadData 函数的“完成”回调

    您应该预先初始化 viewModel 或调用 applyBinding 作为回调:

     self.loadData = function (callback) {
            $.get("/api/Template/Get", { id: self.TemplateId() }).done(function (data) {
                self.Data(ko.mapping.fromJS(data));
                alert(self.Data().PlateTemplateGroups().length);
    
                if(typeof callback === 'function')
                    callback();
            });
        }
    

    不在视图模型构造函数中调用 loadData

    $(document).ready(function () {
        var viewModel = new PlateTemplateViewModel();
        if (!viewModel.CreateMode()) {
            viewModel.loadData(function(){
                ko.applyBindings(viewModel, $("#plateTemplate")[0]);
            });
        }
    });
    

    【讨论】:

    • 控制台中的错误是“Uncaught TypeError: Unable to process binding “foreach: function (){return Data().PlateTemplateGroups() }”消息:无法读取未定义的属性“PlateTemplateGroups” .对不起,我应该说的。
    • 你能告诉我你在哪里调用applyBindings方法吗?
    • 已添加到问题中。
    • $.get 是异步函数。您确定 ko.applyBindings 在服务器返回数据后执行吗?您可以将 preinit 用于 PlateTemplateGroups(添加到答案中)
    • 哇,@RomanKiyashev!那行得通!我不知道你做了什么,但屏幕现在加载。但是有些项目没有加载。我正在加载的对象是一个包含 4 个项目(字符串和整数)的类,以及一个 List。 PlateTemplateGroup 包含一个 List。这样两个列表已经加载...但是包含对象中的项目没有加载。
    猜你喜欢
    • 2020-04-08
    • 1970-01-01
    • 2019-07-17
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    相关资源
    最近更新 更多