使用动态字段为 table 创建敲除组件

Create knockout component for table with dynamic fields

我正在尝试为 table 创建一个带有动态行和列的剔除组件。要求是两者兼而有之,行和列都可以有控件。像这样 -

                    <dynamic-table params="data: item">
                        <header-template>
                           <label>Column1</label>
                            <label>Column2</label>
                            <label>Column3</label>
                            <a href="#">Column 4</a>
                        </header-template>
                        <body-template params="showButtons: ['Edit', 'Delete']">
                            <label>FieldValue0</label>
                            <label>FieldValue1</label>
                            <label>FieldValue2</label>
                            <label>FieldValue3</label>
                            <input type="text" value="FieldValue4"></input>
                        </body-template>
                    </dynamic-table>

我正在考虑的方法是在 ko 组件中为页眉和正文创建一个单独的模板。 $componentTemplateNodes 在这里可能对我有帮助,但我不知道如何使用它。关于此的任何样本都将非常有用。

这样的事情怎么样:

JsFiddle

HTML:

<dyno-table params="headerData: { title: title }, rowData: rows">
  <header-template>
    <h2>HELLO! <span data-bind="text: title"></span></h2>
  </header-template>
  <row-template>
    <div>Name: <span data-bind="text: name"></span>, Age: <span data-bind="text: age"></span></div>
  </row-template>
</dyno-table>

<template id='dyno-table-template'>
  <!-- ko template: { nodes: headerNodes, data: headerData } -->
  <!-- /ko -->
  <!-- ko template: { nodes: rowNodes, foreach: rowData } -->
  <!-- /ko -->
  <!-- ko template: { nodes: footerNodes, data: footerData } -->
  <!-- /ko -->
</template>

JavaScript:

ko.components.register("dyno-table", { 
  viewModel: { createViewModel: createViewModel },
  template: { element: 'dyno-table-template' }
});

function createViewModel(params, componentInfo) {
  var headerNodes = getChildNodes(componentInfo.templateNodes, 'header-template'),
    rowNodes = getChildNodes(componentInfo.templateNodes, 'row-template'),
    footerNodes = getChildNodes(componentInfo.templateNodes, 'footer-template');

  return {
    headerNodes: headerNodes,
    headerData: params.headerData,
    rowNodes: rowNodes,
    rowData: params.rowData,
    footerNodes: footerNodes,
    footerData: params.footerData
  };
}

function getChildNodes(allNodes, tagName) {
    var lowerTagName = tagName.toLowerCase(),
    node = ko.utils.arrayFirst(allNodes, function(node) { return node.tagName && node.tagName.toLowerCase() === lowerTagName; }),
    children = (node ? node.childNodes : null);

  return children;
}

var model = {
  title: ko.observable('A TABLE!'),
  rows: ko.observableArray([
    { name: ko.observable('Max'), age: ko.observable(12) },
    { name: ko.observable('Max2'), age: ko.observable(13) },
    { name: ko.observable('Max3'), age: ko.observable(14) },
    { name: ko.observable('Max4'), age: ko.observable(15) },
    { name: ko.observable('Max5'), age: ko.observable(16) },
    { name: ko.observable('Max6'), age: ko.observable(17) },
  ]),
  farewell: ko.observable('Farewell!')
};

ko.applyBindings(model);

这只是我在考虑与您要解决的问题类似的问题时遇到的问题。根据您的使用情况,它可能适合您。

有几点需要注意:

  1. 如果使用它来创建一个真正的 table,您不能像人们希望的那样在页眉中开始标记并在页脚中关闭它。该问题可能有解决方案,但这只是一次快速尝试。
  2. 可能不支持缺失data/templates等,但您可以根据需要自定义。
  3. 使用 -template 元素的子节点,而不是节点本身。显然可以根据需要进行修改。