6

I have a html table and the rows come form an observable array....

 <tbody data-bind="foreach: TableArray">
     <tr>
         <td data-bind:"text: Item1"></td>

etc....

How can I skip the first row... so I can add a static row (not a header) to the top of the table.

<tbody data-bind="foreach: TableArray">
     <tr> 
        <td> Static Row </td>
     </tr>
     <tr>
         <td data-bind:"text: Item1"></td>
user3147424
  • 3,022
  • 5
  • 19
  • 22

3 Answers3

12

The secret is in the containerless foreach markup. Check "Note 4" of the following link:

http://knockoutjs.com/documentation/foreach-binding.html

Here's a fiddle showing a basic example.

http://jsfiddle.net/internetH3ro/M9f4D/7/

Basic view model:

function ViewModel() {
    var self = this;
    self.items = [{
        firstName: 'James',
        lastName: 'McConnell'
    },{
        firstName: 'Scott',
        lastName: 'Hanselman'
    },{
        firstName: 'Bill',
        lastName: 'Gates'
    }];
}

HTML markup:

<table>
    <tr>
        <th>First Name</th>
        <th>Last Name</th>
    </tr>
    <!-- ko foreach: items -->
    <tr>
        <td><span data-bind="text: $data.firstName"></span></td>
        <td><span data-bind="text: $data.lastName"></span></td>
    </tr>
    <!-- /ko -->
</table>

So you just wrap the content you want repeated in a comment, and Knockout will repeat that content for each element in your collection. Pretty nifty, I wish Angular had something like this.

James McConnell
  • 2,180
  • 3
  • 19
  • 29
  • Agree about Angular; maybe AngularJS does not have the containerless binding syntax, but it does offer a terse syntax that gives what amounts to the same functionality as Knockout's containerless `foreach`. http://stackoverflow.com/a/21446102/538962 – mg1075 Jan 30 '14 at 01:19
  • This is the right answer - shame that "user314..." couldn't be bothered to give you the answer credit. – Mark Brittingham Apr 24 '14 at 12:51
  • Meh, not too worried about it. I come here for help and try to give back when I can, that's all I really care about. :) Thanks for the recognition, though, much appreciated! – James McConnell Apr 29 '14 at 19:07
  • Perfect!!! Saved me! adding `data-bind="foreach: items"` to ``s adds a new ``... BUT (!!!!!) adding it to ``s doesn't create new ``s. – Cody May 13 '14 at 18:44
3

One way to approach the issue would be to use Knockout's containerless binding syntax. See Note 4 in Knockout's documentation of the foreach binding.
http://knockoutjs.com/documentation/foreach-binding.html


Javascript

var YourVM = function () {
    this.allItems = ko.observableArray(["Fries", "Eggs Benedict", "Ham", "Cheese"]);
};

ko.applyBindings(new YourVM());

HTML

     <table>
       <thead>
         <tr>
           <th>Your Column</th>
         </tr>
       </thead>
       <tbody>
         <tr class="row-static">
           <td>Static Row</td>
         </tr>    <!-- ko foreach: allItems -->
         <tr>
           <td data-bind="text: $data"></td>
         </tr>    <!-- /ko -->     
       </tbody>
    </table>

Live example on JS Bin
http://jsbin.com/AzEwEce/1/edit

mg1075
  • 17,985
  • 8
  • 59
  • 100
  • @JamesMcConnell - definitely agree with you about Angular in this regard. https://github.com/angular/angular.js/issues/1891 – mg1075 Jan 29 '14 at 19:49
2

You could use an if binding to only output an extra row on the "first" pass.

Example:

<table data-bind ="foreach: rows">

  <tr data-bind="if: $index() == 0" >
    <td><span data-bind="text: $index"></span></td>
  </tr>
  <tr>
    <td><span data-bind="text: text"></span></td>
  </tr>
</table>
Origineil
  • 3,108
  • 2
  • 12
  • 17