Knockout JS - 无容器控制使用模板打破Foreach

时间:2013-12-04 23:51:38

标签: javascript jquery twitter-bootstrap knockout.js

长篇大论的道歉。希望一些代码能让事情变得更加清晰。

在开始之前,我使用的是KnockoutJs 3.0.0版,bootstrap 3和jquery 1。 7.1。此问题与KnockoutJS有关。

我有以下html,它根据我的基础javascript模型创建一个表单。

        <form role="form" data-bind="foreach: { data: controls, as: 'control' }" >
        <div class="form-group control-form-group" data-bind="attr:{class: $root.cssControlClassColumnWidth }, visible: control.isVisible">
            <fieldset class="control-border" data-bind="
                event:{
                    dragstart: function(control, event) { $root.dragStartControl($parent,control, event) },
                    dragover: function(control, event) { $root.dragOverControl(event) }
                    }">
                <legend class="control-border">
                    <b data-bind="text: control.name"></b>
                    <span class="glyphicon glyphicon-remove-circle btn-control-remove text-danger" data-bind="visible: $root.inCustomisationMode,click: $root.removeControl"></span>
                </legend>
                <div class="form-inline" data-bind="foreach: {data: parameters, as: 'parameter'}">
                    <div class="form-group" >
                        <div data-bind="template: { name: parameter.template, data: parameter }"></div>
                    </div>
                </div>
            </fieldset>
        </div>
    </form>

这很好用。但是当我将代码更改为以下内容(添加无容器控件)时,不会显示使用由parameter.template值确定的模板的内部foreach循环。

        <form role="form" data-bind="foreach: { data: controls, as: 'control' }" >
        <!-- ko if:true -->         
        <div class="row">    
        <!-- /ko -->    
            <div class="form-group control-form-group" data-bind="attr:{class: $root.cssControlClassColumnWidth }, visible: control.isVisible">
                <fieldset class="control-border" data-bind="
                  event:{
                      dragstart: function(control, event) { $root.dragStartControl($parent,control, event) },
                      dragover: function(control, event) { $root.dragOverControl(event) }
                      }">
                    <legend class="control-border">
                        <b data-bind="text: control.name"></b>
                        <span class="glyphicon glyphicon-remove-circle btn-control-remove text-danger" data-bind="visible: $root.inCustomisationMode,click: $root.removeControl"></span>
                    </legend>
                    <div class="form-inline" data-bind="foreach: {data: parameters, as: 'parameter'}">
                        <div class="form-group" >
                            <div data-bind="template: { name: parameter.template, data: parameter }"></div>
                        </div>
                    </div>
                </fieldset>
            </div>
        <!-- ko if:true -->         
        </div>    
        <!-- /ko --> 
    </form>

正如你所看到的,我想要做的就是添加一行(我将添加一个变量,它将控制我在每次运行后每行添加的表单组的数量)。这应该是微不足道的,但我内心的foreach似乎无法使用模板(参见下面的示例模板)。

    <script type="text/html" id="parameterComboBoxTemplate">
    <label data-bind="text: name"></label>
    <select class="input-sm" data-bind="options: values, value: selectedValue"></select>
</script>

希望有人可以解释为什么我会看到这种奇怪的行为。

如果我还有其他任何内容可以帮助您确定问题,请告诉我。

2 个答案:

答案 0 :(得分:3)

Knockout的“无容器控制流语法”使用注释作为“虚拟元素”。他们仍然必须遵守元素规则。这意味着开始和结束标记之间的HTML必须是完整的元素。这就是层次结构的发挥方式:

<form role="form" data-bind="foreach: { data: controls, as: 'control' }" >
    <!-- ko if:true -->         
        <div class="row">    
            <!-- /ko -->             <--- ignored
            <div class="form-group control-form-group" data-bind="attr:{class: $root.cssControlClassColumnWidth }, visible: control.isVisible">
                ...
            </div>
            <!-- ko if:true -->      <--- will generate an error
        </div>    
    <!-- /ko --> 
</form>

答案 1 :(得分:1)

如果有人对我如何解决我的问题感兴趣,请参阅我的代码:

    <form role="form" data-bind="foreach: { data: controls, as: 'control' }" >
        <!-- We only want to create a row of controls on every even number (We may want to change this
            to have a different number of controls in the row so changing the method name to something 
            more generic would be better -->
        <!-- ko if: $root.isRowEven($index()) -->

            <!-- HERE WE WANT TO ADD TWO CONTROLS TO THE ROW!!-->
            <!-- ko if: $parent.controls[$index() + 1] -->
            <div class="row">
                <div class="form-group control-form-group" data-bind="attr:{class: $root.cssControlClassColumnWidth }, visible: control.isVisible">
                    <fieldset class="control-border" data-bind="
                        event:{
                            dragstart: function(control, event) { $root.dragStartControl($parent,control, event) },
                            dragover: function(control, event) { $root.dragOverControl(event) }
                            }">
                        <legend class="control-border"> 

                            <b data-bind="text: control.name"></b>
                            <span class="glyphicon glyphicon-remove-circle btn-control-remove text-danger" data-bind="visible: $root.inCustomisationMode,click: $root.removeControl"></span>
                        </legend>
                        <div class="form-inline" data-bind="foreach: {data: parameters, as: 'parameter'}">
                            <div class="form-group" >
                                <div data-bind="template: { name: parameter.template, data: parameter }"></div>
                            </div>
                        </div>
                    </fieldset>
                </div>
                <div class="form-group control-form-group" data-bind="attr:{class: $root.cssControlClassColumnWidth }, visible: control.isVisible">
                    <fieldset class="control-border" data-bind="
                        event:{
                            dragstart: function(control, event) { $root.dragStartControl($parent,control, event) },
                            dragover: function(control, event) { $root.dragOverControl(event) }
                            }">
                        <legend class="control-border">                   
                            <b data-bind="text: $parent.controls[$index() + 1].name"></b>
                            <span class="glyphicon glyphicon-remove-circle btn-control-remove text-danger" data-bind="visible: $root.inCustomisationMode,click: $root.removeControl"></span>
                        </legend>
                        <div class="form-inline" data-bind="foreach: {data: $parent.controls[$index() + 1].parameters, as: 'parameter'}">
                            <div class="form-group" >
                                <div data-bind="template: { name: parameter.template, data: parameter }"></div>
                            </div>
                        </div>
                    </fieldset>
                </div>
            </div>
            <!-- /ko --> 


            <!-- HERE WE WANT TO ADD ONE CONTROL TO THE ROW!!-->
            <!-- ko if: !$parent.controls[$index() + 1] -->
            <div class="row">
                <div class="form-group control-form-group" data-bind="attr:{class: $root.cssControlClassColumnWidth }, visible: control.isVisible">
                    <fieldset class="control-border" data-bind="
                        event:{
                            dragstart: function(control, event) { $root.dragStartControl($parent,control, event) },
                            dragover: function(control, event) { $root.dragOverControl(event) }
                            }">
                        <legend class="control-border"> 
                            <b data-bind="text: control.name"></b>
                            <span class="glyphicon glyphicon-remove-circle btn-control-remove text-danger" data-bind="visible: $root.inCustomisationMode,click: $root.removeControl"></span>
                        </legend>
                        <div class="form-inline" data-bind="foreach: {data: parameters, as: 'parameter'}">
                            <div class="form-group" >
                                <div data-bind="template: { name: parameter.template, data: parameter }"></div>
                            </div>
                        </div>
                    </fieldset>
                </div>
            </div>
            <!-- /ko --> 

        <!-- /ko -->  




    </form>