如何创建将调用动态部分视图的动态ajax.actionlinks。
例如:
到目前为止我做了什么:
我已经能够创建成功的ajax.actionlink
这将调用控制器并总结投票
这将调用局部视图并显示投票
问题是什么
如何动态完成此操作?
现有代码:
我的剃刀视图中的ajax.actionlink
@Html.Raw(Ajax.ActionLink("[replacetext]", "VoteUp",
new { UserPostID = @Model.Id },
new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = "CountVote" }).ToHtmlString().Replace("[replacetext]",
"<img src=\"/Images/up_32x32.png\" />"))
我的div在同一个剃刀视图中显示部分视图的返回结果。
<div id="CountVote" class="postvotes"></div>
我的控制器
public PartialViewResult VoteUp(int UserPostID)
{
try
{
UserVotes vote = new UserVotes();
vote.SubmitedVote = 1;
vote.UserId = Convert.ToInt32(Session["id"]);
vote.UserPostID = UserPostID;
ViewBag.SumVotes = postRepository.InsertUserPostVote(vote);
}
catch (Exception e)
{
xxx.xxx.xxxx().Raise(e);
}
return PartialView("_TotalVotes");
}
最后是我的部分视图(_TotalVotes.cshtml)
@ViewBag.SumVotes
现在,Viewpost的主视图使用viewbag在循环中显示注释。
foreach (var item in (List<UserComment>)ViewData["Comments"])
{
CommentVote = "cv" + i.ToString();
<div class="postlinewrapper">
<div class="postvotesframe">
<div class="postvotes">
@Html.Raw(Ajax.ActionLink("[replacetext]", "VoteUp",
new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = "CountVote" }).ToHtmlString().Replace("[replacetext]",
"<img src=\"/Images/up_32x32.png\" />"))
</div>
<div id="@CommentVote" class="@CommentVote">0</div>
<div class="postvotes">
@Html.Raw(Ajax.ActionLink("[replacetext]", "VoteDown",
new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = "CountVote" }).ToHtmlString().Replace("[replacetext]",
"<img src=\"/Images/down_32x32.png\" />"))
</div>
</div>
<div class="postleftbar">
@Html.Raw(item.Comment)
</div>
<div class="postrightbar">
<div>
<div class="post_spec">
<div class="post_spec_title">Call Sign: </div>
<div class="post_spec_detail">@item.CallSign</div>
</div>
<div class="post_spec">
<div class="post_spec_title">When: </div>
<div class="post_spec_detail">@item.CommentDate.ToString("dd/MM/yyyy")</div>
</div>
</div>
<br />
<br />
</div>
</div>
i += 1;
}
我已实施登录以上下增加或减少投票:
public PartialViewResult VoteUp(int userPostId)
{
try
{
UserVotes vote = new UserVotes();
vote.SubmitedVote = 1;
vote.UserId = Convert.ToInt32(Session["id"]);
vote.UserPostID = userPostId;
ViewBag.SumVotes = postRepository.InsertUserPostVote(vote);
}
catch (Exception e)
{
xxxx.xxxx.xxxx().Raise(e);
}
return PartialView("_TotalVotes");
}
public PartialViewResult VoteDown(int userPostId)
{
try
{
UserVotes vote = new UserVotes();
vote.SubmitedVote = -1;
vote.UserId = Convert.ToInt32(Session["id"]);
vote.UserPostID = userPostId;
ViewBag.SumVotes = postRepository.InsertUserPostVote(vote);
}
catch (Exception e)
{
xxx.xxxx.xxxx().Raise(e);
}
return PartialView("_TotalVotes");
}
现在所有这些代码都适用于1 ajax调用,但我需要的是动态地为单独的div显示单独的ajax调用。
答案 0 :(得分:5)
以这种方式试试。
主视图
我假设您的模型具有评论项的集合属性Comments
@model MyNamespace.CommentAndOtherStuff
<ul>
@foreach(item in Model.Comments)
{
<li>
<a href="@Url.Action("VoteUp", "VoteControllerName", new { UserPostId = item.Id })"
class="vote-link"
data-id="@item.Id">@item.Votes</a><img src="vote.jpg" />
</li>
}
</ul>
您的控制器只返回一个名为VoteResult
的类作为JSON。
[HttpPost]
public ActionResult VoteUp(int UserPostID)
{
...
var model = new VoteResult
{
UserPostID = UserPostID,
Votes = service.tallyVote(UserPostID)
};
return Json(model);
}
现在用jQuery事件处理程序挂起所有这些并设置一个AJAX调用
$(document).ready(function() {
$("a.vote-link").on("click", function(event) {
event.preventDefault();
var link = $(this); // the link instance that was clicked
var id = link.attr("data-id");
var url = link.attr("href");
$.ajax({
url: url,
type: "post"
})
.done(function(result) {
// JSON result: { UserPostID: 1, Votes: 5 }
// replace link text
link.html(result.Votes);
});
});
});
但我想要部分查看html fagment。
[HttpPost]
public ActionResult VoteUp(int UserPostID)
{
...
var model = new VoteResult
{
UserPostID = UserPostID,
Votes = service.tallyVote(UserPostID)
};
return PartialView("_TotalVotes", model);
}
_TotalVotes partial
@model MyNamespace.VoteResult
@if (Model.Votes < 0)
{
<span class="unpopular">@Model.Votes</span>
}
else
{
<span class="awesome">@Model.Votes</span>
}
调整AJAX回调
.done(function(result) {
link.html(result);
});
现在你可以为链接片段写一个帮助器,但是在我看来它混淆了一些东西(它是一个判断调用)。这里你真正需要的是你的javascript将绑定的类名和数据ID。
答案 1 :(得分:4)
在这里使用Ajax
助手似乎是一种不必要的开销,我建议你只使用jquery方法来更新DOM。您当前的代码表明您可能缺少某些逻辑来使注释投票系统工作,包括指示用户可能已执行的操作。例如(并且假设您希望它与SO类似),如果用户之前已经投票,则点击向上投票链接应该将投票计数减1,但点击向下投票链接应该减少投票数量为2(之前的投票加上新的投票)。
有关如何设置样式并在单击投票元素
时的行为,请参阅this fiddle评论的视图模型可能如下所示
public enum Vote { "None", "Up", "Down" }
public class CommentVM
{
public int ID { get; set; }
public string Text { get; set; }
public Vote CurrentVote { get; set; }
public int TotalVotes { get; set; }
}
并假设您的模型包含一组注释
public class PostVM
{
public int ID { get; set; }
public string Text { get; set; }
public IEnumerable<CommentVM> Comments { get; set; }
}
以及相关的DisplayTemplate
/Views/Shared/DisplayTemplates/CommentVM.cshtml
@model CommentVM
<div class="comment" data-id="@Model.ID" data-currentvote="@Model.CurrentVote">
<div class="vote">
<div class="voteup" class="@(Model.CurrentVote == Vote.Up ? "current" : null)"></div>
<div class="votecount">@Model.TotalVotes</div>
<div class="votedown" class="@(Model.CurrentVote == Vote.Down ? "current" : null)"></div>
</div>
<div class="commenttext">@Html.DisplayFor(m => m.Text)</div>
</div>
然后在主视图中
@model PostVM
.... // display some properties of Post?
@Html.DisplayFor(m => m.Comments)
<script>
var voteUpUrl = '@Url.Action("VoteUp")';
var voteDownUrl = '@Url.Action("VoteDown")';
$('.voteup').click(function() {
var container = $(this).closest('.comment');
var id = container.data('id');
var voteCount = new Number(container.find('.votecount').text());
$.post(voteUpUrl, { id: id }, function(response) {
if (!response) {
// oops, something went wrong - display error message?
return;
}
container.find('.votecount').text(response.voteCount); // update vote count
if (response.voteCount < voteCount) {
// the user previously upvoted and has now removed it
container.find('.voteup').removeClass('current');
} else if (response.voteCount == voteCount + 1) {
// the user had not previously voted on this comment
container.find('.voteup').addClass('current');
} else if (response.voteCount == voteCount + 2) {
// the user previoulsy down voted
container.find('.votedown').removeClass('current');
container.find('.voteup').addClass('current');
}
});
});
$('.votedown').click(function() {
... // similar to above (modify logic in if/elseif blocks)
});
</script>
和控制器方法
public JsonResult VoteUp(int id)
{
int voteCount = // your logic to calculate the new total based on the users current vote (if any) for the comment
return Json(new { voteCount = voteCount });
}