Rafiki
Rafiki

Reputation: 698

Knockout passing object to a computed function

I have a MVC table that is being filled with data. Each row of data has a secondary list of data attached to it. I'm trying to pull the first value I come to out of that secondary list and populate that field on the table.

The problem is the header object is undefined during runtime when the function is called for some reason. The ko loop is looping on the Header object and the Detail object is where the data is I need. Both Header and Detail are children of Orders

Here is the html table with the ko function call:

<tbody data-bind="with: $root.Orders">
                        <!-- ko foreach: OrdersList -->
                        <!-- ko with: Header -->
                        <tr>                                
                            <td class="text-left" style="padding: 2px !important;"><span id="localPO" data-bind="text: $root.SubsetNumber()"></span></td>                                
                        </tr>
                        <!-- /ko -->
                        <!-- /ko -->
                    </tbody>

Here is the ko function:

vmHomeIndex.SubsetNumber = ko.computed(function (header) {
            var details = header.$parents.Details;
            var poNumber = 1;
            return poNumber;
        }, vmHomeIndex);

So my question is why is header undefined?

Upvotes: 0

Views: 924

Answers (2)

David Sherret
David Sherret

Reputation: 106870

header is undefined because a computed observable's evaluator function will never have any arguments passed into it.

You can solve this by adding a SubsetNumber computed to each of your items in vmHomeIndex.OrdersList and referencing the current item's details.

Alternatively, you could also call a function and pass in Header's parent. For example:

vmHomeIndex.getSubsetNumber = function (order) {
    var header = order.Header;   // example to get header
    var details = order.Details; // then to get details
    var poNumber = 1;
    return poNumber;
};

Then change this code:

data-bind="text: $root.SubsetNumber()"

To instead pass in Header's parent—$parent in this context:

data-bind="text: $root.getSubsetNumber($parent)"

Upvotes: 3

McCroskey
McCroskey

Reputation: 1171

The anonymous functions passed into computed observables don't take parameters. Hence, when the function you defined with header as a parameter is invoked by Knockout, the parameter is undefined.

Also, note that, as written, your function never actually does anything with the value of details. That being said, if you want to access the header in a computed observable and do something with it, you can do the following:

vmHomeIndex.SubsetNumber = function(header) {
    return ko.computed(function () {
          var details = header.$parents.Details;
          var poNumber = 1;

          /* Do some magic here with Details to generate a poNumber */

          return poNumber;
    }, vmHomeIndex);
}

You can then reference it by doing:

<span data-bind="text: $root.SubsetNumber($data)"></span>

In this case, SubsetNumber is a function returning an observable. If you just return a value from SubsetNumber, then the span will not be updated should anything in the Details view model change.

Upvotes: 1

Related Questions