在Controller

时间:2017-07-10 07:40:25

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

我正在尝试将我的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>();

    }

该类中的List项声明为:

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

    }

然后在THAT列表中,作为对象:

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; }
}

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

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>

什么都没发生。这是因为某些事情尚未初始化吗?甚至可以这样做吗?控制台窗口中出现错误:

  

未捕获的TypeError:无法处理绑定“foreach:function   (){return Data()。PlateTemplateGroups()}“消息:无法读取   属性'PlateTemplateGroups'未定义

在调试器中,如果我在加载数据后断点...我看到了这个: enter image description here

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

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

它显示了PlateTemplateGroups列表中的第一个项目,我可以看到'Components'中的项目(这也是一个列表。这一切看起来都是可观察的,因为我将它们作为函数访问。

我的视图模型applybindings发生在我的js文件的末尾:

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

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

1 个答案:

答案 0 :(得分:2)

您在浏览器控制台中有错误吗?你确定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函数的'done'回调

您应该预先启动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]);
        });
    }
});