Use MVC helpers inside jquery.tmpl templates

北战南征 提交于 2019-12-04 19:53:44

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

Martijn

option 1: - your posts viewmodel is probably coming from the server, it could contain the link.

{
title:'post title', 
commentsUrl:'/Indivdualpost/comments/123'
} 

on the server

 return new post { comment='post title', commentsUrl=Url.Action('Comments','Individualposts', new {id=1234}); }

and then render the comments url in the template:

 <a data-bind="attr: {href:commentsUrl}">comments</a>

option 2: script using a form

<form id="frm" action="@Url.Action("Comments","IndividualPost")>
<input type="hidden" name="id" id="postid"/>
<!-- template stuff -->
</form>

and in the template

<p class="post-footer">
    <a data-bind="click:function(){ $('#postid').val(${$id}); $('#frm').submit(); }">comments</a>
</p>

(the click attribute is quite ugly, should be improved using a binding handler or a viewmodel function ( http://www.knockmeout.net/2011/08/simplifying-and-cleaning-up-views-in.html ))

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!