【问题标题】:Knockout template with both different td cells and one common td cell具有不同 td 细胞和一个常见 td 细胞的敲除模板
【发布时间】:2018-01-10 10:13:56
【问题描述】:

我使用下面的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>

我需要在模板中添加什么来实现它?

【问题讨论】:

    标签: javascript html templates knockout.js


    【解决方案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>
    

    完整的sn-p:

    (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));
    <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>

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-22
      • 1970-01-01
      • 1970-01-01
      • 2015-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多