Chris Nevill
Chris Nevill

Reputation: 6151

Detecting Selected Row in html table Knockout/ASP.NET MVC

I've loaded an ASP.NET MVC viewModel into KnockoutJS using ko.mapping.fromJS(Model).

My viewModel looks something like this:

public IEnumerable<FunkyThing>funkyThings;
public FunkyThing selectedFunkyThing;

I've then got in my HTML View a table which looks something like this

<tbody data-bind="foreach: funkyThings">
    <tr>
        <td data-bind="text:name"></td>  
        <td data-bind="text:funkiness"></td>  
        <td><a href='#' title="Select Funky Thing" data-bind="click: $root.selectFunkyThing"></a>
       </td>
    </tr>
</tbody>

and all is good with this table. Clicking the select funky thing link happily calls the selectFunkyThing function:

    model.selectFunkyThing= function (funkyThing) {
        window.location = '@Url.Action(MVC.FunkyThingController.Index())' + "?funkyThingID=" + funkyThing.funkyThingID();

    };

which in turn refreshes the page. The MVC viewmodels is reloaded and selectedFunkyThing is populated with the selected FunkyThing and the knockout view models are then re-read from the MVC viewmodel. So far so good.

I then wanted to update the table to highlight the selected entry. So I updated the tr line as follows:

<tr data-bind="css:{'selected': $root.isSelected()}">

and created the new knockout function:

 model.isSelected = function (funkyThing) {
            return funkyThing.funkyThingID== model.selectedFunkyThing.funkyThingID;

        };

but... it's not working. Chrome throws a javascript exception stating that the FunkyThing parameter is undefined. Technically I figure I could solve it by changing the MVC viewModel to actually set a isSelected on each FunkyThing within the array. However I figure there's got to be away of doing this from Knockout?

Upvotes: 2

Views: 2394

Answers (2)

scaryman
scaryman

Reputation: 1900

You were close! I added the ko.utils.unwrapObservable call because I bet the funkyThingID is an observable and not just a straight property - you did this yourself in your selectFunkyThing function. You could just execute them as well. I like the verbosity of unwrap though.

model.isSelected = function (funkyThing) {
  var thisId = ko.utils.unwrapObservable(model.selectedFunkyThing.funkyThingID);
  return ko.utils.unwrapObservable(funkyThing.funkyThingID) == thisId;
};

and then in your document you actually have to execute this function when ko parses the binding

<tr data-bind="css:{'selected': $root.isSelected($data)}">

Upvotes: 2

Paul Manzotti
Paul Manzotti

Reputation: 5147

Are those properties not both observables, so you need to reference them as functions? You also need to make your function a computed observable, I think:

model.isSelected = ko.computed(function (funkyThing) {
    return funkyThing().funkyThingID() == model.selectedFunkyThing().funkyThingID();
});

Upvotes: 1

Related Questions