具有不同td细胞和一个常见td细胞的敲除模板

时间:2018-01-10 10:13:56

标签: javascript html templates knockout.js

我使用以下html作为模板来构建表(这实际上是Knockout的simpleGrid模板):

<script type='text/html' id='template'> 
    <table class="table table-bordered table-condensed" >
       <thead>
          <tr class="active" data-bind="foreach: columns">
             <th data-bind="text: headerText"></th>
          </tr>
       </thead>
       <tbody data-bind="foreach: data">
          <tr data-bind="foreach: $parent.columns">
             <td data-bind="text: typeof rowText == 'function' ? rowText($parent) : $parent[rowText] "></td>
          </tr>
       </tbody>
    </table>
</script>

这样我就可以使用不同的模型来创建具有不同列的网格。例如(taken from here,有一些更改):

(function () {
    // Private function
    function getColumnsForScaffolding(data)
    {
        if ((typeof data.length !== 'number') || data.length === 0)
        {
            return [];
        }
        var columns = [];
        for (var propertyName in data[0])
        {
            columns.push({ headerText: propertyName, rowText: propertyName });
        }
        return columns;
    }

    ko.simpleGrid = {
        // Defines a view model class you can use to populate a grid
        viewModel: function (configuration)
        {
            this.data = configuration.data;
            this.columns = configuration.columns;
        }
    };

    // Templates used to render the grid
    var templateEngine = new ko.nativeTemplateEngine();

    templateEngine.addTemplate = function (templateName, templateMarkup)
    {
        document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "<" + "/script>");
    };

    templateEngine.addTemplate("ko_simpleGrid_grid", "\
                <table class=\"table table-bordered table-condensed\" >\
                    <thead>\
                        <tr class=\"active\" data-bind=\"foreach: columns\">\
                           <th data-bind=\"text: headerText\"></th>\
                        </tr>\
                    </thead>\
                    <tbody data-bind=\"foreach: data\">\
                       <tr data-bind=\"foreach: $parent.columns\">\
                           <td data-bind=\"text: typeof rowText == 'function' ? rowText($parent) : $parent[rowText] \"></td>\
                        </tr>\
                    </tbody>\
                </table>");

    // The "simpleGrid" binding
    ko.bindingHandlers.simpleGrid = {
        init: function ()
        {
            return { 'controlsDescendantBindings': true };
        },
        // This method is called to initialize the node, and will also be called again if you change what the grid is bound to
        update: function (element, viewModelAccessor, allBindings)
        {
            var viewModel = viewModelAccessor();

            // Empty the element
            while (element.firstChild)
                ko.removeNode(element.firstChild);

            // Allow the default templates to be overridden
            var gridTemplateName = "ko_simpleGrid_grid",
                gridFooterTemplateName = "ko_simpleGrid_gridFooter";

            // Render the main grid
            var gridContainer = element.appendChild(document.createElement("DIV"));
            ko.renderTemplate(gridTemplateName, viewModel, { templateEngine: templateEngine }, gridContainer, "replaceNode");
        }
    };
})();


var initialData = [
    { name: "Well-Travelled Kitten", sales: 352, price: 75.95 },
    { name: "Speedy Coyote", sales: 89, price: 190.00 },
];
 
var PagedGridModel = function(items) {
    this.items = ko.observableArray(items);
    this.gridViewModel = new ko.simpleGrid.viewModel({
        data: this.items,
        columns: [
            { headerText: "Item Name", rowText: "name" },
            { headerText: "Sales Count", rowText: "sales" },
            { headerText: "Price", rowText: function (item) { return "$" + item.price.toFixed(2) } }
        ]
    });
};
 
ko.applyBindings(new PagedGridModel(initialData));
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<div data-bind='simpleGrid: gridViewModel'> </div>

现在,我希望能够根据模型生成td元素,但也有一个“常用”td,其中会有一些按钮,类似:

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<table class="table table-bordered table-condensed">                    
  <thead>                  
    <tr class="active" data-bind="foreach: columns">                           
      <th>Item Name</th>
      <th>Sales Count</th>
      <th>Price</th>
      <th>Action</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Well-Travelled Kitten</td>
      <td>352</td>
      <td>$75.95</td>
      <td>
         <button type="button" class="btn btn-default" title="Delete">
	   <span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
         </button>
      </td>
    </tr>
    <tr>
      <td>Speedy Coyote</td>
      <td>89</td>
      <td>$190.00</td>
      <td>
         <button type="button" class="btn btn-default" title="Delete">
	   <span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
         </button>
      </td>
    </tr> 
  </tbody>
</table>

我需要将哪些内容添加到模板中才能实现?

1 个答案:

答案 0 :(得分:1)

最简单的解决方案是为数组中的表格单元格创建虚拟元素绑定,并在下方直接添加其他单元格。例如:

<tbody data-bind="foreach: data">
    <tr>
      <!-- ko foreach: $parent.columns -->
        <td data-bind="text: typeof rowText == 'function' ? rowText($parent) : $parent[rowText] "></td>
      <!-- /ko -->

      <td data-bind="click: $parent.columns.remove.bind($parent)">delete</td>
    </tr>
</tbody>

完整摘录:

&#13;
&#13;
(function () {
    // Private function
    function getColumnsForScaffolding(data)
    {
        if ((typeof data.length !== 'number') || data.length === 0)
        {
            return [];
        }
        var columns = [];
        for (var propertyName in data[0])
        {
            columns.push({ headerText: propertyName, rowText: propertyName });
        }
        return columns;
    }

    ko.simpleGrid = {
        // Defines a view model class you can use to populate a grid
        viewModel: function (configuration)
        {
            this.data = configuration.data;
            this.columns = configuration.columns;
        }
    };

    // Templates used to render the grid
    var templateEngine = new ko.nativeTemplateEngine();

    templateEngine.addTemplate = function (templateName, templateMarkup)
    {
        document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "<" + "/script>");
    };

    templateEngine.addTemplate("ko_simpleGrid_grid", "\
                <table class=\"table table-bordered table-condensed\" >\
                    <thead>\
                        <tr class=\"active\">\
                        <!-- ko foreach: columns -->\
                           <th data-bind=\"text: headerText\"></th>\
                           <!-- /ko -->\
                           <th>Action</th>\
                        </tr>\
                    </thead>\
                    <tbody data-bind=\"foreach: data\">\
                       <tr>\
                           <!-- ko foreach: $parent.columns -->\
        <td data-bind=\"text: typeof rowText == 'function' ? rowText($parent) : $parent[rowText] \"></td>\
      <!-- /ko -->\
                         <td>\
         <button type=\"button\" class=\"btn btn-default\" title=\"Delete\">\
	   <span class=\"glyphicon glyphicon-trash\"></span>\
         </button>\
      </td>\
      </tr>\
      </tbody>\
      </table>");

    // The "simpleGrid" binding
    ko.bindingHandlers.simpleGrid = {
        init: function ()
        {
            return { 'controlsDescendantBindings': true };
        },
        // This method is called to initialize the node, and will also be called again if you change what the grid is bound to
        update: function (element, viewModelAccessor, allBindings)
        {
            var viewModel = viewModelAccessor();

            // Empty the element
            while (element.firstChild)
                ko.removeNode(element.firstChild);

            // Allow the default templates to be overridden
            var gridTemplateName = "ko_simpleGrid_grid",
                gridFooterTemplateName = "ko_simpleGrid_gridFooter";

            // Render the main grid
            var gridContainer = element.appendChild(document.createElement("DIV"));
            ko.renderTemplate(gridTemplateName, viewModel, { templateEngine: templateEngine }, gridContainer, "replaceNode");
        }
    };
})();


var initialData = [
    { name: "Well-Travelled Kitten", sales: 352, price: 75.95 },
    { name: "Speedy Coyote", sales: 89, price: 190.00 },
];
 
var PagedGridModel = function(items) {
    this.items = ko.observableArray(items);
    this.gridViewModel = new ko.simpleGrid.viewModel({
        data: this.items,
        columns: [
            { headerText: "Item Name", rowText: "name" },
            { headerText: "Sales Count", rowText: "sales" },
            { headerText: "Price", rowText: function (item) { return "$" + item.price.toFixed(2) } }
        ]
    });
};
 
ko.applyBindings(new PagedGridModel(initialData));
&#13;
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<div data-bind='simpleGrid: gridViewModel'> </div>
&#13;
&#13;
&#13;

或者,您可以创建RegularCellActionCell元素的组合数组,并使用template绑定和动态模板选择器函数在不同类型的模板之间切换。这是well documented on the knockout site