Search code examples
asp.net-mvcknockout.jshelperjquery-templates

Use MVC helpers inside jquery.tmpl templates


I have a simple foreach template and inside every element I want an ActionLink but that ActionLink needs to send an Id to edit the element.

The item to be templated:

<div data-bind="template: {
                    name: 'postsTemplate',
                    foreach: posts
                    }">
</div>

The template:

<script id="postsTemplate" type="text/html">
<h2 data-bind="text: Title"></h2>

<p class="post-info">
    <p class="post-info" data-bind="text UserName"></p>
    <span data-bind="Body"></span>
    <p class="post-footer">
        @Html.ActionLink("Comments", "IndividualPost", "Post", null, null, "comments", new {id = })
    </p>
</p>
</script>

How can I send the actual post Id through the ActionLink? I mean, How I can access to the post's id without using data-bind? (Because it's a helper).


Solution

  • If you would implement your own ActionLink extension along the line of:

    public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText,
                                           string actionName, string controllerName,
                                           object routeValues,  bool noEncode)
        {
            var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
            var url = urlHelper.Action(actionName, controllerName, routeValues);
    
            if (noEncode) url = Uri.UnescapeDataString(url);
    
            var tagBuilder = new TagBuilder("a");
    
            tagBuilder.MergeAttribute("href", url);
            tagBuilder.InnerHtml = linkText;
    
            return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
        }
    

    Then you could make your template like:

    <p class="post-info">
        <p class="post-info" data-bind="text UserName"></p>
        <span data-bind="Body"></span>
        <p class="post-footer">
            @Html.ActionLink("Comments (${CommentCount})", "IndividualPost", "Post", 
                             new {id = "${id}"}, true)
        </p>
    </p>
    

    the serverside html generated would then look like:

    <p class="post-info">
        <p class="post-info" data-bind="text UserName"></p>
        <span data-bind="Body"></span>
        <p class="post-footer">
           <a href="/Post/IndividualPost/${id}">Comments (${CommentCount})</a>
        </p>
    </p>
    

    which in turn is a perfect template in my opinion.

    The reason for an ActionLink extension is the fact that the normal Html.ActionLink encodes your url to /Post/IndividualPost/%24%7Bid%7D which doesn't work for the template