franco
franco

Reputation: 697

How to make a column value appear only once using Knockout?

I am using Knockout to generate a table that loops through a list of objects; however, there is a column that I only want to appear once. In the example below:

Group | Component | Description |
---------------------------------
A     | Comp 1    | Desc 1      |
A     | Comp 2    | Desc 2      |
B     | Comp 3    | Desc 3      |
B     | Comp 4    | Desc 4      |

I would want the final output to look like this:

Group | Component | Description |
---------------------------------
A     | Comp 1    | Desc 1      |
      | Comp 2    | Desc 2      |
B     | Comp 3    | Desc 3      |
      | Comp 4    | Desc 4      |

Is there a way to do this via jQuery or some other framework?

Edit

Sample code: https://jsfiddle.net/on6Lby1c/

Upvotes: 2

Views: 100

Answers (2)

4imble
4imble

Reputation: 14416

Anoops answer works but I personally prefer to avoid inline calculations. As such you can offload this calculation to a function and bind to that on the viewmodel via $parent.

Don't forget to sort if you want 0 duplicates :)

var vm = function() {
  var data = new ko.observableArray([
    { group: 'A', component: 'Component 1', description: 'Description 1' },
    { group: 'A', component: 'Component 2', description: 'Description 2' },
    { group: 'B', component: 'Component 3', description: 'Description 3' },
    { group: 'B', component: 'Component 4', description: 'Description 4' },
  ]);

  function groupValue(index) {
  	var underlyingArray = data();
    if(index == 0)
      return underlyingArray[0].group;

    return underlyingArray[index-1].group == underlyingArray[index].group	
    	? "" : underlyingArray[index].group;
  }

  return {
    data: data,
    groupValue: groupValue
  }
}

ko.applyBindings(new vm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<table>
    <thead>
        <tr><th>Group</th><th>Component</th><th>Description</th></tr>
    </thead>
    <tbody data-bind="foreach: data">
        <tr>
            <td data-bind="text: $parent.groupValue($index())"></td>
            <td data-bind="text: component"></td>
            <td data-bind="text: description"></td>
        </tr>
    </tbody>
</table>

https://jsfiddle.net/fv9x3s20/

Upvotes: 1

Anoop H.N
Anoop H.N

Reputation: 1264

Change the code as below, It will work.

<table>
    <thead>
        <tr><th>Group</th><th>Component</th><th>Description</th></tr>
    </thead>
    <tbody data-bind="foreach: myObj">
        <tr>
            <td data-bind="text: $index()-1 >= 0?  ($parent.myObj[$index()-1].group == group? '' : group):group"></td>
            <td data-bind="text: component"></td>
            <td data-bind="text: description"></td>
        </tr>
    </tbody>
</table>

Updated fiddle,

https://jsfiddle.net/on6Lby1c/1/

Upvotes: 0

Related Questions