Static row above knockout.js observable array table
Asked Answered
E

3

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>
Eraeradiate answered 29/1, 2014 at 18:20 Comment(0)
S
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.

Snot answered 29/1, 2014 at 19:0 Comment(4)
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. https://mcmap.net/q/138902/-angularjs-ng-repeat-with-no-html-elementMisgive
This is the right answer - shame that "user314..." couldn't be bothered to give you the answer credit.Septuplet
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!Snot
Perfect!!! Saved me! adding data-bind="foreach: items" to <tbody>s adds a new <tbody>... BUT (!!!!!) adding it to <tr>s doesn't create new <tr>s.Iormina
M
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

Misgive answered 29/1, 2014 at 19:2 Comment(1)
@JamesMcConnell - definitely agree with you about Angular in this regard. github.com/angular/angular.js/issues/1891Misgive
V
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>
Verger answered 29/1, 2014 at 19:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.