Knockout JS:创建动态表列

时间:2018-03-22 15:50:43

标签: javascript knockout.js

使用Knockout JS:

我有一个要求。

我有一个包含2个静态列的表,每个列都有一个文本框。我在表格外面还有一个添加行按钮,每行都有一个删除行按钮。

当用户点击添加行时,它会在表格中添加一行,我可以看到两列中包含文本框。如果需要,用户可以通过单击添加行添加更多行,然后单击删除行以删除行。

这一切都已设置好并且可以正常工作:

https://jsfiddle.net/aman1981/xmd1xobm/14/

我的问题是还有一个获取列按钮。当用户单击此按钮时,我会获取列的列表,并希望使用标题添加这些列,而不是表中已有的列。这些列中的每一列也需要有一个文本框。

对于ex,我将列列表为:

 var columnsList = 'name, address, zip';

我不确定如何动态添加列。希望得到投入。

以下是我的表格的设置:

<table class="table table-bordered">
  <thead class="mbhead">
<tr class="mbrow">
  <th>SIID</th>
  <th>Comment</th>      
</tr>
  </thead>
  <tbody data-bind="foreach: data">
   <tr>
    <td>
     <input type="text" data-bind="text: SIID" class="form-control textbox" />
  </td>      
  <td> 
   <input type="text" data-bind="text: Comment" class="form-control textbox" />
  </td>  
   <td>
    <input type="button" value="Remove Row" data-bind="click: $parent.removeRow" class="btn btn-danger" />
  </td>
</tr>
 </tbody>

<div class="col-xs-12 col-sm-6">
 <input type="button" value="Add Row" class="btn btn-primary" data-bind="click: addRow" /> 
  <input type="button" value="Get Columns" class="btn btn-primary" data-bind="click: addColumns" /> 
</div>

任何?

2 个答案:

答案 0 :(得分:0)

很高兴我有一个来自我之前项目的动态表组件:

var observable = ko.observable;
var pureComputed = ko.pureComputed;
var observableArray = ko.observableArray;
var unwrap = ko.unwrap;

var data = observableArray([{
  a: 123,
  b: 234,
  c: 345
},{
  a: 1231,
  b: 2341,
  c: 3451
},{
  a: 1232,
  b: 2342,
  c: 3425
},{
  a: 1233,
  b: 2343,
  c: 3453
}]);

var columns = observableArray([{
    field: "a",
    displayName: "A"
},{
    field: "b",
    displayName: "B (i can even change the title)"
}])

function viewModel(params) {
    var paramColumns = params.columns;
    var paramData = params.data;
    var paramFieldKey = params.fieldKey || "field";
    var paramDisplayNameKey = params.displayNameKey || "displayName";

    var koColumnHeaders = pureComputed(function () {
        var columns = paramColumns();
        var columnHeaders = [];
        var fieldKey = unwrap(paramFieldKey);
        var displayNameKey = unwrap(paramDisplayNameKey);
        for (var i in columns) {
            var column = columns[i];
            columnHeaders.push({
                field: column[fieldKey],
                displayName: column[displayNameKey]
            })
        }
        return columnHeaders;
    })

    var koRows = pureComputed(function () {
        var data = paramData();
        var columns = paramColumns();
        var fieldKey = unwrap(paramFieldKey);
        var rows = [];
        for (var i in data) {
            var datum = data[i];
            var cells = []
            var row = {
                entity: data,
                cells: cells
            };
            for (var j in columns) {
                var column = columns[j];
                cells.push(datum[column[fieldKey]] || "");
            }
            rows.push(row);
        }
        return rows;
    });


    return {
        rows: koRows,
        columns: koColumnHeaders,
    }
}

ko.applyBindings(new viewModel({
    data: data,
    columns: columns
}))
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

    <table class="table table-bordered" border="1">
        <thead>
            <tr data-bind="foreach: columns">

                <th data-bind="text: displayName">
                </th>

            </tr>
        </thead>
        <tbody data-bind="foreach: rows">
            <tr>
                <!-- ko foreach: cells -->
                <td class="" data-bind="text: $data"></td>
                <!-- /ko -->
            </tr>
        </tbody>
    </table>

答案 1 :(得分:0)

我能够使用以下帖子解决此问题: Knockout JS: Get Textbox data from Table under for-each binding

这是我的代码:

 (function() {
var ViewModel = function() {
var self = this;
self.valuesData = ko.observableArray();

self.columns = ko.computed(function() {
  if (self.valuesData().length === 0)
    return [];

  return ValuesData.columns;
});


self.addRow = function() {
  self.valuesData.push(new ValuesData());
};

self.Save = function() {
  alert('Data:')
};

self.removeRow = function(data) {
  self.valuesData.remove(data);
};
}

// Dynamic values.
var ValuesData = function(siid, comment) {
var self = this;

// Add observables dynamically for all relevant columns.
for (var i = 0; i < ValuesData.columns.length; i++) {
  var column = ValuesData.columns[i];
  self[column.Property] = ko.observable(column.InitialValue)
 }
};

// Basic column definition.
ValuesData.columns = [{
  Caption: 'SIID',
  Property: 'SIID',
  InitialValue: undefined
},
{
  Caption: 'Column 1',
  Property: 'Col1',
  InitialValue: undefined
},
{
  Caption: 'Column 2',
  Property: 'Col2',
  InitialValue: 'banana'
},
{
  Caption: 'Comment',
  Property: 'Comment',
  InitialValue: undefined
}
]

vm = new ViewModel()
ko.applyBindings(vm);

// add initial row.
vm.addRow();


})();

这是html部分:

 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-
 min.js"></script>
  <br><br>
<table>
 <thead>
 <!-- NEW: use ko foreach with 'as' to have an alias for accessing $data. -->
 <tr data-bind="foreach: { data: columns, as: 'column'}">
  <th> <span data-bind="text: column.Caption"></span>
  </th>
 </tr>
</thead>
  <tbody data-bind="foreach: { data: valuesData, as: 'rowData'}">
  <tr data-bind="foreach: { data: $parent.columns, as: 'column' }">
  <!-- NEW: bind to the corresponding property/observable in ValuesData -->
  <td><input type="text" class="form-control textbox" data-bind="textInput: 
 rowData[column.Property]" /> </td>
  </tr>
   <tr>
   <td>
    <input type="button" value="Remove Row" data-bind="click: 
 $parent.removeRow" class="btn btn-danger" />
    </td>
  </tr>
</tbody>