RawPodolski
RawPodolski

Reputation: 33

$index with if binding not working

I have a block of code where I'm trying to show some mark up based on $index value and comparing it with an observable.

<div class='config-summary-chart-section'>
  <!-- ko foreach: codeCoverageStats -->
  <div class='config-stat-chart-section'>
  <div class='chart-heading' data-bind='text: lengthArray ' />
  <div class='chart-heading' data-bind='text: $index ' />                         
</div>        
<!-- ko if: $index() !== lengthArray -->                           
<div class='separator' />                                        
  <!-- /ko -->                                  
  <!-- /ko -->
</div>

Both my class='chart-heading' are printing values as expected. Here for example if the lengthArray is 4 then this prints

4   4   4   4   4 
0   1   2   3   4

But the if condition ($index() !== lengthArray) is not being honored for the last index and I get the last separator class which I want to avoid. What is going wrong here?

Upvotes: 0

Views: 169

Answers (2)

TSV
TSV

Reputation: 7641

For now we can only guess about your view model structure.

If the "lengthArray" is an observable, you need unwrap its value:

<!-- ko if: $index() !== lengthArray() -->

or

<!-- ko if: $index() !== ko.unwrap(lengthArray) -->

Explanations

We should unwrap observables when we using them as arguments for calculations. Let's say "lengthArray" is an observable. This means that "lengthArray" is a function (reference to a function). So write

1 + lengthArray

is a mistake because you are adding two different objects objects: a number and a function reference.

If you write "lengthArray()" - you are calling the "lengthArray" function and getting its actual value, that you can use in computations:

1 + lengthArray()

If you don't know whether "lengthArray" is an observable or not, you can use KnockoutJS utility function: "ko.unwrap(lengthArray)" to get the value for operation.

This is what KnockoutJS does for arguments of bindings. That's why we needn't do it manually when using bindings.

Upvotes: 0

Roy J
Roy J

Reputation: 43881

Most likely your lengthArray value is a string, which is not identical to a number. One easy way to assure a numeric value is to prepend a + to it. No hr is generated after the element at index 4 in the example below.

function la(lengthValue) {
  return {
    lengthArray: lengthValue
  };
}
vm = {
  codeCoverageStats: ko.observableArray([
    la(4),
    la(4),
    la(4),
    la(4),
    la('4'),
    la(4)
  ])
};

ko.applyBindings(vm);
.config-stat-chart-section > div {
  display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class='config-summary-chart-section'>
  <!-- ko foreach: codeCoverageStats -->
  <div class='config-stat-chart-section'>
    <div class='chart-heading' data-bind='text: lengthArray '></div>
    <div class='chart-heading' data-bind='text: $index '></div>
  </div>
  <!-- ko if: $index() !== +lengthArray -->
  <hr />
  <!-- /ko -->
  <!-- /ko -->
</div>

Upvotes: 1

Related Questions