knockout绑定动态类型

时间:2013-12-30 18:24:55

标签: razor knockout.js knockout-mapping-plugin

我在MVC中有一个名为Entity的模型,其中包含Properties,这些属性的值可以是3件事之一。 Unit,DropDownSelection或本机类型(int,string,datetime等)。 Unit和DropDownSelection非常简单,但它们的显示方式与本机类型不同(DropDownSelection - > DropDown,Native - > Input,Unit - > Input + DropDown)。

我个人知道基于Property [0] .DataType但是如何将该信息适当地传递给Knockout,以便它在Select Control中显示DropDownSelections,在Inputs中显示Native Type等。

当前视图

@model List<NMBS.EntityModels.Entity>

@* Page Content *@
<h1><span class="entity-type" data-bind="text: $data[0].EntityType"></span></h1>
<a data-bind="attr: { href: '/Entity/Create?EntityType=' + $data[0].EntityType() }" class="ignore">New</a>
<form>
    <table>
        <thead>
            <tr data-bind="template: { name: 'HeaderRowTemplate', foreach: $data[0].Properties }">
                <td data-bind="text: Name, visible: SummaryProperty"></td>
            </tr>
        </thead>
        <tbody data-bind="template: { name: 'DataRowTemplate', foreach: $data }">

        </tbody>
    </table>
</form>

@* Templates *@
<script id="HeaderRowTemplate" type="text/html">
    <td data-bind="text: Name, visible: SummaryProperty"></td>
</script>

<script id="DataRowTemplate" type="text/html">
    <tr data-bind="template: { name: 'DataItemTemplate', foreach: Properties }"></tr>
</script>

<script id="DataItemTemplate" type="text/html">
    <td data-bind="text: Value.ValueAsString, visible: SummaryProperty"></td>
</script>

@* Scripts *@
<script type="text/javascript">
    function ApplyBindings() {
        var data = @Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model)),
            viewModel = ko.mapping.fromJS(data);
        ko.applyBindings(viewModel);
    }
    ApplyBindings();
</script>

实体属性

public Int32 ID { get; set; }
public String EntityType { get; set; }
public Int32? ParentID { get; set; }
public Int32? PropertyValueID { get; set; }
public List<Property> Properties { get; set; }
public Entities Children { get; set; }
public Boolean IsValueEntity { get; set; }

属性

public Int32 ID { get; set; }
public String Name { get; set; }
public String DataType { get; set; }
public Boolean Required { get; set; }
public Boolean OnlyOne { get; set; }
public Boolean ForceNew { get; set; }
public dynamic Value { get; set; }
public String ValueAsString { get; set; }
public Boolean SummaryProperty { get; set; }

问题:我如何将数据绑定值(即Entity [i] .Property [i] .Value)转到正确的Html控件?有没有办法明确或隐含地告诉它使用特定模板的某些DataType值(Entity [i] .Properties [i] .DataType)?

1 个答案:

答案 0 :(得分:2)

我想你需要考虑编写自己的自定义绑定处理程序。 http://knockoutjs.com/documentation/custom-bindings.html

请注意,即使是data-bind =“text:fooVar”也只是一个预定义的绑定处理程序,您可以随时使用自己的自定义扩展程序来扩展。

在您的情况下,我会采取以下路线:

首先,重新定义您的加价以适应我们将要撰写的处理程序:

<script id="DataItemTemplate" type="text/html">
    <td data-bind="visible: SummaryProperty">
        <label data-bind="text: Value.ValueAsString" />
        <input data-bind="customFormControl: Value" />
    </td>
</script>

其次,我们定义我们的处理程序。在这种情况下,我选择测试您的DataType属性,然后将子元素添加到表格单元格中。

ko.bindingHandlers.customFormControl = {
    init: function ( element, valueAccessor, allBindings, viewModel, bindingContext ) {
        var val = valueAccessor(),
            dataType = bindingContext.$data.DataType;
        if ( dataType == 'Unit' ) {
            // define and replace 'element'
        } else if ( dataType == 'DropDownSelection') {
            // define and replace 'element'
        } else { 
            // control is already an input, so this shouldn't need any work
        }
    }, update: function ( element, valueAccessor, allBindings, viewModel, bindingContext ) {
        // do as you wish when the values are updated.
    }
}

关键是要了解更多有关这些参数的消息,淘汰赛正在向您抛出。一旦你理解了bindingHandlers,你就会意识到你可以通过Knockout完成任何你需要做的事情,并且上下文始终可用。

祝你好运。