具有映射插件的Knockout视图模型

时间:2014-05-30 14:52:03

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

我正在试图弄清楚如何在我的视图模型中使用Knockout映射引擎。

如果我有一个如下所示的服务器端视图模型:

public class InventoryIndexViewModel
{
    public bool IsDeleteReceiverButtonVisible { get; set; }
    public IList<Receiver> Receivers { get; set; }

    public string ReceiversAsJson
    {
        get
        {
            var jsonSerializerSettings = new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            };

            var receivers = JsonConvert.SerializeObject(this.Receivers, jsonSerializerSettings);

            return receivers;
        }
    }

}

Receiver属性是一个如下所示的对象:

public class Receiver
{
    public Cooperative Cooperative { get; set; }
}

Cooperative属性是一个如下所示的对象:

public class Cooperative
{
    public int Id { get; set; }
    public string Name { get; set; }
}

我的观点如下:

@model InventoryIndexViewModel

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "Inventory List";
}

@section scripts{
    <script>
        $(function() {
            var inventoryViewModel = function() {

                var self = this;

                self.isDeleteButtonVisible = function() { return @Model.IsDeleteReceiverButtonVisible.ToString().ToLower(); }();
                self.receivers = ko.observableArray(@Html.Raw(Model.ReceiversAsJson));
            };

            ko.applyBindings(new inventoryViewModel());
        });
    </script>
}

<div class="col-md-10">
    <br />
    <table class="table table-striped">
        <tbody data-bind="foreach: receivers">
            <tr>
                <td data-bind="text: serialNumber"></td>
                <td data-bind="text: cooperative.Name"></td>
            </tr>
        </tbody>
    </table>
</div>

所以问题是,如何使用复杂的Receiver对象。在我的视图代码中,我尝试将数据绑定到cooperative.Name,但这不起作用。我猜我需要使用Knockout映射插件,但是我已经尝试了Knockout页面的语法以及Googling找到的几种不同的语法变体,但我尝试过的任何东西似乎都没有用。

在旁注中,此处显示的代码与我的实际代码相比大大简化了。因此,虽然在这个简化的代码中可能有一种非常简单的方法来通过数据绑定到达cooperative.Name,但只要考虑Receiver对象是一个复杂的对象,它有很多属性本身就是复杂的对象,所以这就是Knockout映射引擎将完成整个对象层次结构中将所有内容转换为可观察对象的繁重工作。

或许它不能和我离开基地。想法?

编辑:更新了服务器端视图模型,以正确包含我最初忘记包含的ReceiversAsJson方法。

1 个答案:

答案 0 :(得分:1)

如果您的属性在模型中定义,您可以使用映射将模型序列化为json,如下所示:

<强>的Javascript

    var data = @Html.Raw(Json.Encode(Model));
    var viewModel = ko.mapping.fromJS(data);
    ko.applyBindings(viewModel);

查看

<table class="table table-striped">
        <tbody data-bind="foreach: Receivers">
            <tr>

                <td data-bind="text: Cooperative.Name"></td>
            </tr>
        </tbody>
</table>

<强>的jsfiddle

http://jsfiddle.net/wr5W7/

带示例数据的控制器

        public ActionResult Index()
        {
            var model = new InventoryIndexViewModel();
            model.IsDeleteReceiverButtonVisible = false;
            model.Receivers.Add(new Receiver { Cooperative = new Cooperative { Id = 1, Name = "aName" } });

            return View(model);
        }

<强>模型

ps我必须在集合中添加一个初始化程序,即

    public class InventoryIndexViewModel
    {
        public InventoryIndexViewModel()
        {
            Receivers = new List<Receiver>();
        }

        public bool IsDeleteReceiverButtonVisible { get; set; }
        public IList<Receiver> Receivers { get; set; }
    }

    public class Receiver
    {
        public Cooperative Cooperative { get; set; }
    }

    public class Cooperative
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

<强>更新

根据评论,这是一种使用带有淘汰计算函数的映射插件的方法:

<强>的Javascript

var aViewModel = function(data)
{
   self = this;
   ko.mapping.fromJS(data, {}, self);

   self.firstNameAndLastName = ko.computed(function() {
        return self.FirstName() + " " + self.LastName();
    }); 

}


var data = {"IsDeleteReceiverButtonVisible":false, "FirstName": "First", "LastName": "Last", "Receivers":[{"Cooperative":{"Id":1,"Name":"aName"}}]};
        var viewModel = new aViewModel(data);
        ko.applyBindings(viewModel);

<强> HTML

<table class="table table-striped">
        <tbody data-bind="foreach: Receivers">
            <tr>

                <td data-bind="text: Cooperative.Name"></td>
            </tr>
        </tbody>
    </table>
<span data-bind="text:firstNameAndLastName()"></span>

<强>的jsfiddle

http://jsfiddle.net/wr5W7/3/