Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knockout foreach in the middle of a table

I have a table like so:

<table>
 <thead>
  <tr>
   <td>Column 1</td><td>Column 2</td>
  </tr>
 </thead>
  <tr>
   <td>static 1a</td><td>static 2a</td>
  </tr>
  <tr>
   <td>dynamic 1b</td><td>dynamic 2b</td>
  </tr>
  <tr>
   <td>dynamic 1c</td><td>dynamic 2c</td>
  </tr>
 </table>

The dynamic fields need to be a knockout foreach to iterate all the properties of the object. The only thing I can think to do is something like:

    <tbody data-bind="foreachprop: properties">
        <tr><td><span data-bind="text: propertyName"></span></td><td><span data-bind="text: value"></span></td></tr>
    </tbody>

Which technically works, but it screws with my styling because the static row should be part of the tbody. What else can I bind to the for each? I must be missing a simple solution.

update: I'm actually not using "foreach", I'm using a custom function that iterates through the properties. When I try to use <!-- ko foreachprop:> properties -- I get the following console error:

Uncaught Error: The binding 'foreachprop' cannot be used with virtual elements

Here is the foreachprop function

ko.bindingHandlers.foreachprop = {
    transformObject: function (obj) {
        var properties = [];
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                var newObj = obj[key];
                newObj.propertyName = key;
                properties.push(newObj);
            }
        }
        return properties;
    },
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var value = ko.utils.unwrapObservable(valueAccessor()),
            properties = ko.bindingHandlers.foreachprop.transformObject(value);
        ko.applyBindingsToNode(element, { foreach: properties });
        return { controlsDescendantBindings: true };
    }
};
like image 346
THE JOATMON Avatar asked May 21 '13 19:05

THE JOATMON


1 Answers

You can use foreach without a container element (documentation: note 4) To handle this, you can use the containerless control flow syntax. You just need a specfial comment line where you can put your foreach:

<tbody data-bind="">
   <tr>
     <td>static 1a</td><td>static 2a</td>
   </tr>
   <!-- ko foreach: properties -->
      <tr>
         <td>
             <span data-bind="text: propertyName"></span>
         </td>
         <td>
             <span data-bind="text: value"></span>
         </td>
     </tr>
   <!-- /ko -->
</tbody>

If you are using a custom binding foreachprop then you need to configure it work with virtual elements. You can do with after the bindingHandlers declaration with:

ko.virtualElements.allowedBindings.foreachprop = true;

You should note that you may need to rewrite your DOM manipulation logic inside your custom binding to support the virtual elements. You can find an extensive documentation on the virtualElements helpers in the documentation: Creating custom bindings that support virtual elements

like image 115
nemesv Avatar answered Dec 21 '22 17:12

nemesv