如何编辑 Post 回复 Post 视图而不在单独的视图中执行此操作
How to edit Post Reply on Post View without doing that in a separate View
我正在创建一个论坛。这是一个 ASP.NET Core 3.1 MVC 应用程序。
在 post 索引视图中,顶部有一个 post 标题和内容,post 回复列在下面,带有一个 foreach 循环。我想在同一个视图上实现 EDIT 功能,而不必创建新的单独视图。
我已经为 post 构建了 EDIT 函数。当用户单击 post 上的“编辑”按钮时,会弹出一个 EditPostModal
,它就像一个魅力。这对我来说是一项非常容易的任务,因为一个 post 视图只有一个对应的 post.
现在我想对每个回复做类似的事情。我现在遇到的问题是,如果我将用于编辑回复的新模态 window 放在我用于显示回复的同一个 foreach 循环中,我将能够访问所有相关属性以填充模态信息,但是弄得一团糟。首先,我认为每个回复都有一个模式有点不合适。此外,现在每个模态实际上都是相同的模态,但具有不同的信息(不同的隐藏 ID 和内容),当我单击提交按钮时,出现 @reply.Id
的空异常,我假设是因为它试图通过从所有模态一次到控制器的信息很混乱。
另一方面,当我将模态 window 放在 foreach 循环之外时,我无法通过模型访问 post 回复信息。或者我根本不知道如何实现。
请在下面找到代码(经过简化,只有相关部分)。
查看型号:
public class PostIndexModel
{
public int Id { get; set; }
public string Title { get; set; }
public DateTime CreatedOn { get; set; }
public string PostContent { get; set; }
public IEnumerable<PostReplyModel> Replies { get; set; }
}
public class PostReplyModel
{
public int Id { get; set; }
public DateTime CreatedOn { get; set; }
public string ReplyContent { get; set; }
}
Post 查看 Index.cshtml:
@model WebProjectAircraftForum.Models.Post.PostIndexModel
<div class="container">
<div class="row PostIndex-PostContent">
<div class="PostContent-Container">
<div class="PostContent-Header">
@Model.CreatedOn
</div>
<div class="PostContent-Text">
@Html.Raw(Model.PostContent)
</div>
<div class="PostContent-Footer">
@if (User.Identity.Name == Model.AuthorName || User.IsInRole("Admin"))
{
<a class="ClassicButton Button-EditPost" data-target="#modalEditPost" onclick="toggleModalPost()">
Edit
</a>
}
</div>
</div>
</div>
foreach (var reply in Model.Replies)
{
<div class="row PostIndex-ReplyContent">
<div ReplyContent-Container">
<div class="PostContent-Header">
@reply.CreatedOn
</div>
<div class="PostContent-Text">
@Html.Raw(reply.ReplyContent)
</div>
<div class="PostContent-Footer">
@if (User.Identity.Name == Model.AuthorName || User.IsInRole("Admin")) //added
{
<a class="ClassicButton Button-EditPost" data-target="#modalEditPost" onclick="toggleModalPostReply()">
Edit
</a>
}
</div>
</div>
</div>
//modal for edit PostReply
<div class="modal fade" id="modalEditPostReply" tabindex="-1" role="dialog" aria-labelledby="modalEditPostReply" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="EditPostFormHeader">
Edit Post Reply
</div>
<form id="EditPostForm1" class="EditPostForm" asp-controller="Post" asp-action="EditReply" method="post">
<input asp-for="@reply.Id" type="hidden" />
<div class="EditPostTextarea">
<textarea rows="10" asp-for="@reply.ReplyContent" required></textarea>
<label asp-for="@reply.ReplyContent"></label>
<span asp-validation-for="@reply.ReplyContent" class="text-danger"></span>
</div>
<div class="CreatePostButtonRow">
<input type="submit" value="edit reply" />
</div>
</form>
</div>
</div>
</div>
</div>
负责接受这个的 PostController
部分:
[Authorize]
[HttpPost]
public async Task<IActionResult> EditReply(PostReplyModel model)
{
var reply = _postService.GetReplyById(model.Id);
await _postService.EditPostReplyContent(reply.Id, model.ReplyContent);
return RedirectToAction("Index", new { id = model.PostId });
}
你能帮忙吗?有什么方法可以将模态跳出循环并仍然能够做到这一点?提前致谢。
第一种使用循环的方式
查看(Index.cshtml):
1.You不分享什么是toggleModalPost
和toggleModalPostReply
js函数。实际上不需要使用任何js函数来弹出模态。只需使用默认 bootstrap 属性 data-toggle="modal"
.
2.Your modal id 是 modalEditPostReply
但锚点中 data-target
的值不匹配。此外,所有模态都应拥有唯一的 ID。您需要添加索引以使其唯一。
@model PostIndexModel
@{ int i = 0;} <!--add here -->
<div class="container">
<div class="row PostIndex-PostContent">
<div class="PostContent-Container">
<div class="PostContent-Header">
@Model.CreatedOn
</div>
<div class="PostContent-Text">
@Html.Raw(Model.PostContent)
</div>
<div class="PostContent-Footer"> <!--Not sure which modal does this edit button launch-->
<a class="ClassicButton Button-EditPost" data-toggle="modal" data-target="#modalEditPost_@i">
EditPost
</a>
</div>
</div>
</div>
@foreach (var reply in Model.Replies)
{
<div class="row PostIndex-ReplyContent">
<div ReplyContent-Container">
<div class="PostContent-Header">
@reply.CreatedOn
</div>
<div class="PostContent-Text">
@Html.Raw(reply.ReplyContent)
</div>
<div class="PostContent-Footer"> <!--add data-toggle and change data-target -->
<a class="ClassicButton Button-EditPost" data-toggle="modal" data-target="#modalEditPostReply_@i" >
EditReply
</a>
</div>
</div>
</div>
//modal for edit PostReply
//modify the id....
<div class="modal fade" id="modalEditPostReply_@i" tabindex="-1" role="dialog" aria-labelledby="modalEditPostReply" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="EditPostFormHeader">
Edit Post Reply
</div>
<form id="EditPostForm1" class="EditPostForm" asp-controller="Post" asp-action="EditReply" method="post">
<input asp-for="@reply.Id" type="hidden" />
<div class="EditPostTextarea">
<textarea rows="10" asp-for="@reply.ReplyContent" required></textarea>
<label asp-for="@reply.ReplyContent"></label>
<span asp-validation-for="@reply.ReplyContent" class="text-danger"></span>
</div>
<div class="CreatePostButtonRow">
<input type="submit" value="edit reply" />
</div>
</form>
</div>
</div>
</div>
i++; //add here...
}
</div>
控制器:
您的前端使用 asp-for="@reply.PropertyName"
,它将生成 name="reply.PropertyName"
,您需要指定前缀。
[HttpPost]
public async Task<IActionResult> EditReply([Bind(Prefix ="reply")]PostReplyModel model)
{
return RedirectToAction("Index");
}
避免循环的第二种方式
您可以使用局部视图来重用模态。
查看(Index.cshtml):
现在可以使用js函数调用ajax加载局部视图,避免模态循环
@model PostIndexModel
<div class="container">
<div class="row PostIndex-PostContent">
<div class="PostContent-Container">
<div class="PostContent-Header">
@Model.CreatedOn
</div>
<div class="PostContent-Text">
@Html.Raw(Model.PostContent)
</div>
<div class="PostContent-Footer">
<a class="ClassicButton Button-EditPost" data-target="#modalEditPost">
EditPost
</a>
</div>
</div>
</div>
@foreach (var reply in Model.Replies)
{
<div class="row PostIndex-ReplyContent">
<div ReplyContent-Container">
<div class="PostContent-Header">
@reply.CreatedOn
</div>
<div class="PostContent-Text">
@Html.Raw(reply.ReplyContent)
</div>
<div class="PostContent-Footer">
<a class="ClassicButton Button-EditPost" data-target="#modalEditPostReply"
onclick="toggleModalPostReply('@reply.Id')">
EditReply
</a>
</div>
</div>
</div>
<div id="loadModal">
<!--load the modal-->
</div>
}
</div>
@section Scripts
{
<script>
function toggleModalPostReply(id) {
$.ajax({
type: "Get",
url: "/Post/LoadPartial?id="+id,
success: function (data) {
$("#loadModal").html(data);
$('#modalEditPostReply').modal('show')
}
})
}
</script>
}
部分视图(_Partial.cshtml 位于 Views/Shared 文件夹中):
@model PostReplyModel
<div class="modal fade" id="modalEditPostReply" tabindex="-1" role="dialog" aria-labelledby="modalEditPostReply" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="EditPostFormHeader">
Edit Post Reply
</div>
<form id="EditPostForm1" class="EditPostForm" asp-controller="Post" asp-action="EditReply" method="post">
<input asp-for="Id" type="hidden" />
<div class="EditPostTextarea">
<textarea rows="10" asp-for="ReplyContent" required></textarea>
<label asp-for="ReplyContent"></label>
<span asp-validation-for="ReplyContent" class="text-danger"></span>
</div>
<div class="CreatePostButtonRow">
<input type="submit" value="edit reply" />
</div>
</form>
</div>
</div>
</div>
控制器:
public IActionResult LoadPartial(int id)
{
var data = _context.Replies.Where(i => i.Id == id).FirstOrDefault();
return PartialView("_Partial", data);
}
[HttpPost]
public async Task<IActionResult> EditReply(PostReplyModel model)
{
return RedirectToAction("Index");
}
我正在创建一个论坛。这是一个 ASP.NET Core 3.1 MVC 应用程序。
在 post 索引视图中,顶部有一个 post 标题和内容,post 回复列在下面,带有一个 foreach 循环。我想在同一个视图上实现 EDIT 功能,而不必创建新的单独视图。
我已经为 post 构建了 EDIT 函数。当用户单击 post 上的“编辑”按钮时,会弹出一个 EditPostModal
,它就像一个魅力。这对我来说是一项非常容易的任务,因为一个 post 视图只有一个对应的 post.
现在我想对每个回复做类似的事情。我现在遇到的问题是,如果我将用于编辑回复的新模态 window 放在我用于显示回复的同一个 foreach 循环中,我将能够访问所有相关属性以填充模态信息,但是弄得一团糟。首先,我认为每个回复都有一个模式有点不合适。此外,现在每个模态实际上都是相同的模态,但具有不同的信息(不同的隐藏 ID 和内容),当我单击提交按钮时,出现 @reply.Id
的空异常,我假设是因为它试图通过从所有模态一次到控制器的信息很混乱。
另一方面,当我将模态 window 放在 foreach 循环之外时,我无法通过模型访问 post 回复信息。或者我根本不知道如何实现。
请在下面找到代码(经过简化,只有相关部分)。
查看型号:
public class PostIndexModel
{
public int Id { get; set; }
public string Title { get; set; }
public DateTime CreatedOn { get; set; }
public string PostContent { get; set; }
public IEnumerable<PostReplyModel> Replies { get; set; }
}
public class PostReplyModel
{
public int Id { get; set; }
public DateTime CreatedOn { get; set; }
public string ReplyContent { get; set; }
}
Post 查看 Index.cshtml:
@model WebProjectAircraftForum.Models.Post.PostIndexModel
<div class="container">
<div class="row PostIndex-PostContent">
<div class="PostContent-Container">
<div class="PostContent-Header">
@Model.CreatedOn
</div>
<div class="PostContent-Text">
@Html.Raw(Model.PostContent)
</div>
<div class="PostContent-Footer">
@if (User.Identity.Name == Model.AuthorName || User.IsInRole("Admin"))
{
<a class="ClassicButton Button-EditPost" data-target="#modalEditPost" onclick="toggleModalPost()">
Edit
</a>
}
</div>
</div>
</div>
foreach (var reply in Model.Replies)
{
<div class="row PostIndex-ReplyContent">
<div ReplyContent-Container">
<div class="PostContent-Header">
@reply.CreatedOn
</div>
<div class="PostContent-Text">
@Html.Raw(reply.ReplyContent)
</div>
<div class="PostContent-Footer">
@if (User.Identity.Name == Model.AuthorName || User.IsInRole("Admin")) //added
{
<a class="ClassicButton Button-EditPost" data-target="#modalEditPost" onclick="toggleModalPostReply()">
Edit
</a>
}
</div>
</div>
</div>
//modal for edit PostReply
<div class="modal fade" id="modalEditPostReply" tabindex="-1" role="dialog" aria-labelledby="modalEditPostReply" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="EditPostFormHeader">
Edit Post Reply
</div>
<form id="EditPostForm1" class="EditPostForm" asp-controller="Post" asp-action="EditReply" method="post">
<input asp-for="@reply.Id" type="hidden" />
<div class="EditPostTextarea">
<textarea rows="10" asp-for="@reply.ReplyContent" required></textarea>
<label asp-for="@reply.ReplyContent"></label>
<span asp-validation-for="@reply.ReplyContent" class="text-danger"></span>
</div>
<div class="CreatePostButtonRow">
<input type="submit" value="edit reply" />
</div>
</form>
</div>
</div>
</div>
</div>
负责接受这个的 PostController
部分:
[Authorize]
[HttpPost]
public async Task<IActionResult> EditReply(PostReplyModel model)
{
var reply = _postService.GetReplyById(model.Id);
await _postService.EditPostReplyContent(reply.Id, model.ReplyContent);
return RedirectToAction("Index", new { id = model.PostId });
}
你能帮忙吗?有什么方法可以将模态跳出循环并仍然能够做到这一点?提前致谢。
第一种使用循环的方式
查看(Index.cshtml):
1.You不分享什么是toggleModalPost
和toggleModalPostReply
js函数。实际上不需要使用任何js函数来弹出模态。只需使用默认 bootstrap 属性 data-toggle="modal"
.
2.Your modal id 是 modalEditPostReply
但锚点中 data-target
的值不匹配。此外,所有模态都应拥有唯一的 ID。您需要添加索引以使其唯一。
@model PostIndexModel
@{ int i = 0;} <!--add here -->
<div class="container">
<div class="row PostIndex-PostContent">
<div class="PostContent-Container">
<div class="PostContent-Header">
@Model.CreatedOn
</div>
<div class="PostContent-Text">
@Html.Raw(Model.PostContent)
</div>
<div class="PostContent-Footer"> <!--Not sure which modal does this edit button launch-->
<a class="ClassicButton Button-EditPost" data-toggle="modal" data-target="#modalEditPost_@i">
EditPost
</a>
</div>
</div>
</div>
@foreach (var reply in Model.Replies)
{
<div class="row PostIndex-ReplyContent">
<div ReplyContent-Container">
<div class="PostContent-Header">
@reply.CreatedOn
</div>
<div class="PostContent-Text">
@Html.Raw(reply.ReplyContent)
</div>
<div class="PostContent-Footer"> <!--add data-toggle and change data-target -->
<a class="ClassicButton Button-EditPost" data-toggle="modal" data-target="#modalEditPostReply_@i" >
EditReply
</a>
</div>
</div>
</div>
//modal for edit PostReply
//modify the id....
<div class="modal fade" id="modalEditPostReply_@i" tabindex="-1" role="dialog" aria-labelledby="modalEditPostReply" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="EditPostFormHeader">
Edit Post Reply
</div>
<form id="EditPostForm1" class="EditPostForm" asp-controller="Post" asp-action="EditReply" method="post">
<input asp-for="@reply.Id" type="hidden" />
<div class="EditPostTextarea">
<textarea rows="10" asp-for="@reply.ReplyContent" required></textarea>
<label asp-for="@reply.ReplyContent"></label>
<span asp-validation-for="@reply.ReplyContent" class="text-danger"></span>
</div>
<div class="CreatePostButtonRow">
<input type="submit" value="edit reply" />
</div>
</form>
</div>
</div>
</div>
i++; //add here...
}
</div>
控制器:
您的前端使用 asp-for="@reply.PropertyName"
,它将生成 name="reply.PropertyName"
,您需要指定前缀。
[HttpPost]
public async Task<IActionResult> EditReply([Bind(Prefix ="reply")]PostReplyModel model)
{
return RedirectToAction("Index");
}
避免循环的第二种方式
您可以使用局部视图来重用模态。
查看(Index.cshtml):
现在可以使用js函数调用ajax加载局部视图,避免模态循环
@model PostIndexModel
<div class="container">
<div class="row PostIndex-PostContent">
<div class="PostContent-Container">
<div class="PostContent-Header">
@Model.CreatedOn
</div>
<div class="PostContent-Text">
@Html.Raw(Model.PostContent)
</div>
<div class="PostContent-Footer">
<a class="ClassicButton Button-EditPost" data-target="#modalEditPost">
EditPost
</a>
</div>
</div>
</div>
@foreach (var reply in Model.Replies)
{
<div class="row PostIndex-ReplyContent">
<div ReplyContent-Container">
<div class="PostContent-Header">
@reply.CreatedOn
</div>
<div class="PostContent-Text">
@Html.Raw(reply.ReplyContent)
</div>
<div class="PostContent-Footer">
<a class="ClassicButton Button-EditPost" data-target="#modalEditPostReply"
onclick="toggleModalPostReply('@reply.Id')">
EditReply
</a>
</div>
</div>
</div>
<div id="loadModal">
<!--load the modal-->
</div>
}
</div>
@section Scripts
{
<script>
function toggleModalPostReply(id) {
$.ajax({
type: "Get",
url: "/Post/LoadPartial?id="+id,
success: function (data) {
$("#loadModal").html(data);
$('#modalEditPostReply').modal('show')
}
})
}
</script>
}
部分视图(_Partial.cshtml 位于 Views/Shared 文件夹中):
@model PostReplyModel
<div class="modal fade" id="modalEditPostReply" tabindex="-1" role="dialog" aria-labelledby="modalEditPostReply" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="EditPostFormHeader">
Edit Post Reply
</div>
<form id="EditPostForm1" class="EditPostForm" asp-controller="Post" asp-action="EditReply" method="post">
<input asp-for="Id" type="hidden" />
<div class="EditPostTextarea">
<textarea rows="10" asp-for="ReplyContent" required></textarea>
<label asp-for="ReplyContent"></label>
<span asp-validation-for="ReplyContent" class="text-danger"></span>
</div>
<div class="CreatePostButtonRow">
<input type="submit" value="edit reply" />
</div>
</form>
</div>
</div>
</div>
控制器:
public IActionResult LoadPartial(int id)
{
var data = _context.Replies.Where(i => i.Id == id).FirstOrDefault();
return PartialView("_Partial", data);
}
[HttpPost]
public async Task<IActionResult> EditReply(PostReplyModel model)
{
return RedirectToAction("Index");
}