Search code examples
knockout.jsknockout-3.0kogrid

Knockout KOGrid Hyperlink within a cell


I have an ASP.Net MVC5 app which returns a view model to several fields, one of which contains a URL. When the data from the view model is displayed within the KO Grid I'd like the column containing the hyperlink field to be displayed as a hyperlink.

I've tried using the cellTemplate property of GridOptions but no luck :( To be honest I'm just guessing as to how to reference the value of the field in the view model from the gridOptions.columnDefs so would be grateful for any tips

Here's my view:

@model TVS.ESB.BamPortal.Website.Models.MyTasksViewModel
@using System.Web.Script.Serialization
@{
    ViewBag.Title = "My Tasks";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>@ViewBag.Title</h2>
@{  string data = new JavaScriptSerializer().Serialize(Model); }

<div id="Knockout" data-bind="koGrid: gridOptions">
</div>
<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>


@section Scripts {
    <script src="~/KnockoutVM/Mytasks.js"></script>
    <link rel="stylesheet" type="text/css" href="~/Content/KoGrid.css">
    <script type="text/javascript">
        var vm = new ViewModel(@Html.Raw(data));
        ko.applyBindings(vm, document.getElementById("Knockout"));
    </script>
}

and the relevant parts of my knockout js:

function ViewModel(vm) {
    var self = this;
    this.myData = ko.observableArray(vm.Recs);

    this.gridOptions = {
        data: self.myData,
        enablePaging: true,
        pagingOptions: self.pagingOptions,
        filterOptions: self.filterOptions,
        columnDefs: [{ field: 'Timestamp', displayName: 'Timestamp', width: 90 },
                    { field: 'LinkToFaultsPage', displayName: 'Link to Fault', width: 80, cellTemplate: '<a data-bind="href: $parent.entity[$data.LinkToFaultsPage]" />' }
        ]
    };
};

And my view model that gets send back to the view from the controller:

public class MyTasksViewModel
    {
        public int UserKey { get; set; }
        public List<MyTask> Recs { get; set; }
        public MyTasksViewModel()
        {
            Recs = new List<MyTask>();
        }
    }
    public class MyTask
    {
        public string InterchangeId { get; set; }
        public string State { get; set; }
        public DateTime Timestamp { get; set; }
        public string LinkToFaultsPage { get; set; }
        public string FaultApplication { get; set; }
        public string FaultExceptionMessage { get; set; }
        public string FaultServiceName { get; set; }
    }

Each LinkToFaultsPage field contains a url


Solution

  • The documentation of the custom cell templates is quite good:

    $parent.entity is the current entity of the row, so in your case MyTask object.

    So you can just use $parent.entity.LinkToFaultsPage to access your property

    cellTemplate: '<a data-bind="attr: { href: $parent.entity.LinkToFaultsPage}" >Click Me</a>'
    

    Note that in your original code you don't have a proper attr binding and you also need to add some content to the element (e.g the text "Click Me") so the browsers render out the actual hyperlink.

    If you want to use can also use array indexer syntax:

    cellTemplate: '<a data-bind="attr: { href: $parent.entity[\'LinkToFaultsPage\']}" >Click Me</a>'
    

    If you need more info about cell templates you can also check the Cell Template Library