Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Knockout bindings in MVC ActionLink

I am attempting to utilise KnockoutJS and MVC 4 in order to display a table with ActionLink definitions in the first column of the table. Displaying the data itself is extremely straight-forward and I'm not having any problem there. The problem I have is in the generation of the ActionLink's.

I have taken a look at Use MVC helpers inside jquery.tmpl templates, but the solution there does not utilise knockout templates and inserting the Url into the model object is not feasible (the app domain model objects used to create the view model will be used extensively through out the application).

The table definition:

<table>
    <tbody data-bind="template: { name: 'dmuTableDetail', foreach: tables() }"></tbody>
</table>

(tables is an observable array, hence the parens).

The knockout template definition:

<script id="dmuTableDetail" type="text/html">
    <tr>
        <td>@Html.ActionLink("Details", "Details", "DMUTableCategory", new { @Id = ??? } )</td>
        <td data-bind="text:TableId"></td>
        <td data-bind="text:TableName"></td>
    </tr>
</script>​

The View Model definition:

var PageViewModel = function () {
    self = this;

    self.tables = ko.observableArray([]);

    self.readItems = function () {
        self.tables(jQuery.parseJSON('[{"TableId":1001, "TableName":"Table#1"},{"TableId":1002, "TableName":"Table#2"}]'));
    }
}

$(document).ready(function () {
    vm = new PageViewModel();
    self.readItems('');
    ko.applyBindings(vm);
});

(the actual code performs an Ajax call to retrieve the data, but the code above also demonstrates the issue).

Regardless of what I replace the ??? with, I am unable to get the value of the TableId field to be inserted into the href.

Any help would be greatly appreciated.

Thankyou.

like image 323
John O Avatar asked Aug 10 '12 02:08

John O


1 Answers

Thankyou Eric, you got me thinking about an anchor element and binding the href attribute.

It seems the answer is a little easier than expected (it usually is!).

The table definition: (same as original question)

<table>
    <tbody data-bind="template: { name: 'dmuTableDetail', foreach: tables() }"></tbody>
</table>

The knockout template definition: (change to the binding of the href attribute).

<script id="dmuTableDetail" type="text/html">
    <tr>
        <td><a data-bind="attr: { 'href': '@Url.Action("Details", new RouteValueDictionary() { { "Controller", "DMUTableCategory" } } )/' + TableId }">Details</a></td>
        <td data-bind="text:TableId"></td>
        <td data-bind="text:TableName"></td>
    </tr>
</script>?

The View Model definition: (same as original question)

var PageViewModel = function () {
    self = this;

    self.tables = ko.observableArray([]);

    self.readItems = function () {
        self.tables(jQuery.parseJSON('[{"TableId":1001, "TableName":"Table#1"},{"TableId":1002, "TableName":"Table#2"}]'));
    }
}

$(document).ready(function () {
    vm = new PageViewModel();
    self.readItems('');
    ko.applyBindings(vm);
});

You dont actually need to RootValueDictionary but I've included it so people can see how to change the controller the request is sent to.

like image 134
John O Avatar answered Sep 20 '22 00:09

John O