Knockout JS: Creating dynamic table columns

前端 未结 2 1121
半阙折子戏
半阙折子戏 2020-12-22 00:07

Using Knockout JS:

I have a requirement as.

I have a table with 2 static columns where each has a text-box. I also have a add row button outside the table an

相关标签:
2条回答
  • 2020-12-22 00:59

    I was able to resolve this using the post at: Knockout JS: Get Textbox data from Table under for-each binding

    Here is my code:

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

    Here is the html part:

     <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>
    



    0 讨论(0)
  • 2020-12-22 01:13

    Nice for you i have a dynamic table component from my previous project:

    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>

    0 讨论(0)
提交回复
热议问题