英文:
How to have OnPostAsync work on a PartialView rendered on my Layout?
问题
我有一个布局(_Layout.cshtml
),我想要在它旁边作为一个独立页面渲染一个视图(Feedback.cshtml
),同时保留RenderBody()
的内容。视图本身将从布局的右侧滑出,使用按钮来控制它从右侧滑入和滑出。在该视图中有一个用于反馈的表单。以下是所提到的文件的示例代码:
Layout.cshtml
<div class="feedback">
@await Html.PartialRender("Feedback", new FeedbackModel())
</div>
<div class="content">
@RenderBody()
</div>
Feedback.cshtml
@model FeedbackModel
<div id="offcanvas formContainer">
<form id="feedbackForm" method="post">
<!-- 表单字段 -->
<button type="submit">提交</button>
</form>
</div>
Feedback.cshtml.cs
public class FeedbackModel : PageModel
{
// 属性和字段
public async Task<IActionResult> OnPostAsync()
{
// 处理数据,通过存储库方法将数据添加到数据库
return Page();
}
}
每次我点击反馈页面上的"提交"按钮时,什么都不会发生。它根本不调用OnPostAsync()
方法。如果我在表单上附加asp-page-handler="@Model.OnPostAsync()"
或者在按钮上附加onclick="@Model.OnPostAsync()"
,那么在布局完全加载之前,它会立即触发OnPostAsync()
方法,而我甚至没有打开页面上的部分视图或点击按钮。有人可以提出解决方案吗?
我认为这个逻辑可以移动到一个ViewComponent中,但我不确定如何在唯一提供的方法是InvokeAsync()
时执行OnPostAsync()
。
英文:
I have a layout (_Layout.cshtml
) that i want to render a view (Feedback.cshtml
) onto as a seperate page alongside the RenderBody()
. The view itself will come off from the right hand side of the layout, using a button to toggle it paning to and from the right. On that view there is a form for feedback. Below is example code for the files mentioned:
Layout.cshtml
<div class="feedback">
@await Html.PartialRender("Feedback", new FeedbackModel())
</div>
<div class="content">
@RenderBody()
</div>
Feedback.cshtml
@model FeedbackModel
<div id="offcanvas formContainer">
<form id="feedbackForm" method="post">
<!-- Form fields -->
<button type="submit">Submit</button>
</form>
</div>
Feedback.cshtml.cs
public class FeedbackModel : PageModel
{
<!-- Properties and fields --!>
public async Task<IActionResult> OnPostAsync()
{
<!-- Transform data, Add data to DB via repository methods --!>
return Page();
}
}
Everytime I click the "Submit" button on the Feedback page, it does nothing. It doesn't call the post method at all. If I append a asp-page-hander="@Model.OnPostAsync()"
on the form or an onclick="@Model.OnPostAsync()"
on the button - then before the layout even fully loads, it fires the OnPostAsync()
method immediately, without me even opening the partial view on the page or clicking the button. Can anyone suggest a solution to this?
I thought this logic could instead be moved to a ViewComponent but I am not sure how I would be able to do OnPostAsync()
when the only supplied method is InvokeAsync()
.
答案1
得分: 1
这里是一种方法。创建一个名为Feedback的Razor页面(如您所做),其中包含表单。以下是PageModel:
public class FeedbackModel : PageModel
{
[BindProperty]
public string Comments { get; set; }
[BindProperty]
public string Email { get; set; }
public void OnGet()
{
}
public void OnPost()
{
// 处理反馈
}
}
以下是视图:
@page
@model WebApplication3.Pages.FeedbackModel
@{
Layout = null;
}
<h3 class="fw-light text-muted">提供您的反馈!</h3>
<form id="feedbackForm" method="post">
<div class="form-group mb-3">
<label asp-for="Email" class="control-label"></label>
<input asp-for="Email" class="form-control" />
</div>
<div class="form-group mb-3">
<label asp-for="Comments" class="control-label"></label>
<textarea asp-for="Comments" class="form-control"></textarea>
</div>
<button type="button" class="btn btn-sm btn-success submit" data-bs-dismiss="offcanvas">提交</button>
</form>
请注意,Layout
设置为 null
。我们只需要表单的HTML。此外,提交按钮的 type="button"
,因此在单击时不会提交表单。此外,它通过 data-bs-dismiss
属性与offcanvas关联,以在单击时关闭offcanvas。
将offcanvas的HTML添加到Layout页面:
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasRight">
<div class="offcanvas-body"></div>
</div>
以及一个用于打开它的按钮:
<button type="button" class="btn btn-primary feedback" data-bs-toggle="offcanvas" data-bs-target="#offcanvasRight">反馈</button>
最后,在Layout页面中添加以下脚本,当单击时获取表单的HTML并将其包含在offcanvas中。它还将点击事件处理程序连接到非提交按钮,以将表单内容提交到Feedback页面的OnPost
处理程序:
<script>
const feedbackButton = document.querySelector('button.feedback');
const offCanvas = document.querySelector('#offcanvasRight .offcanvas-body');
feedbackButton.addEventListener('click', _=>{
fetch(`/feedback`).then(response => response.text()).then(html => {
offCanvas.innerHTML = html;
const form = offCanvas.querySelector('#feedbackForm');
const submit = form.querySelector('button.submit');
submit.addEventListener('click', _=>{
const formData = new FormData(form);
fetch(`/feedback`, {
method:'post',
body:new URLSearchParams(formData)
});
})
})
})
</script>
希望这有所帮助!
英文:
So here's one way. Create a Razor page called Feedback (as you have done) containing the form. Here's the PageModel:
public class FeedbackModel : PageModel
{
[BindProperty]
public string Comments { get; set; }
[BindProperty]
public string Email { get; set; }
public void OnGet()
{
}
public void OnPost()
{
// process the feedback
}
}
And here's the view:
@page
@model WebApplication3.Pages.FeedbackModel
@{
Layout = null;
}
<h3 class="fw-light text-muted">Provide your feedback!</h3>
<form id="feedbackForm" method="post">
<div class="form-group mb-3">
<label asp-for="Email" class="control-label"></label>
<input asp-for="Email" class="form-control" />
</div>
<div class="form-group mb-3">
<label asp-for="Comments" class="control-label"></label>
<textarea asp-for="Comments" class="form-control"></textarea>
</div>
<button type="button" class="btn btn-sm btn-success submit" data-bs-dismiss="offcanvas">Submit</button>
</form>
Note that the Layout
is set to null
. We only want the form HTML. Also, the submit button is type="button"
so that the form is NOT submitted when it is clicked. In addition, it is wired up with a data-bs-dismiss
attribute so that it closes the offcanvas when clicked.
Add the offcanvas HTML to the Layout page:
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasRight">
<div class="offcanvas-body"></div>
</div>
Along with a button to open it:
<button type="button" class="btn btn-primary feedback" data-bs-toggle="offcanvas" data-bs-target="#offcanvasRight">Feedback</button>
Finally, add the following script to the Layout page that fetches the HTML for the form when it is clicked and includes it in the offcanvas. It also wires up a click event handler to the non-submit button that posts the content of the form to the OnPost
handler of the Feedback page:
<script>
const feedbackButton = document.querySelector('button.feedback');
const offCanvas = document.querySelector('#offcanvasRight .offcanvas-body');
feedbackButton.addEventListener('click', _=>{
fetch(`/feedback`).then(response => response.text()).then(html => {
offCanvas.innerHTML = html;
const form = offCanvas.querySelector('#feedbackForm');
const submit = form.querySelector('button.submit');
submit.addEventListener('click', _=>{
const formData = new FormData(form);
fetch(`/feedback`, {
method:'post',
body:new URLSearchParams(formData)
});
})
})
})
</script>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论