当更新一个表单(使用 Ajax)时,重新加载表单使它们具有与先前更新的相同的值
Posted
技术标签:
【中文标题】当更新一个表单(使用 Ajax)时,重新加载表单使它们具有与先前更新的相同的值【英文标题】:When one form is updated (using Ajax) reloading the forms make them have the same values as the previously updated one 【发布时间】:2021-12-13 16:18:12 【问题描述】:我正在尝试制作一个简单的 Todo 应用来学习 asp net core mvc。
我使用 CRUD 来管理待办事项,它运行良好。对于下一步,我想尝试向其中添加 Ajax(避免重新加载整个页面),删除工作正常,也创建,但是当我想编辑一个待办事项(基本上是一个表单)时,Ajax 请求的响应集所有待办事项的所有输入都具有相同的值。
如果我将“购买巧克力”作为一个待办事项的标题更新为“购买巧克力”,则所有其他待办事项都会有一个标题“购买巧克力”。
如果我刷新页面(或者只是包含待办事项的部分),一切都会恢复正常,这意味着数据库只更新了我想要的待办事项。
这真的很奇怪,这可能是因为输入具有相同的名称值(todo 1 title => todo.Title、todo 2 title => todo.Title 等),即使它工作正常其余的。
这是包含待办事项容器的页面:
@model IEnumerable<TodoApp.Models.Todo>
@section Css
<link href="/css/todos.css" rel="stylesheet" />
<link href="~/lib/fontawesome/css/all.css" rel="stylesheet" />
@
ViewData["Title"] = "List of todos";
<h1>My list of Todos</h1>
<span class="error-span" style="color:red"></span>
<div id="main_container">
<i onclick="createTodo()" id="create-button" class="fas fa-plus-circle" title="Add new todo"></i>
<div id="todos_container">
@await html.PartialAsync("_TodoList", Model)
</div>
</div>
<partial name="_DeleteModal">
@section Scripts
<script src="~/js/todos.js"></script>
这是显示所有待办事项的 foreach,也是部分视图“_TodoList”:
@model IEnumerable<TodoApp.Models.Todo>
@foreach (Todo todo in Model)
<form class="todo" asp-action="Edit" asp-controller="Todos" data-id="@todo.Id">
<input type="hidden" asp-for="@todo.Id" id="id_@todo.Id" />
<div class="todo-up todo-row">
<textarea autocomplete="off" placeholder="Put the title here..." class="todo-header" asp-for="@todo.Title" id="title_@todo.Id" ></textarea>
<textarea autocomplete="off" placeholder="Put the description here..." class="todo-description" asp-for="@todo.Description" id="decription_@todo.Id" ></textarea>
</div>
<div class="todo-down todo-row">
<div class="todo-validation-row">
<span></span>
<i class="fa-regular fa-check todo-edit" ></i>
<span class="tooltip-text">Saved</span> @*Tooltip for edition*@
</div>
<div class="todo-footer">
<div class="todo-updated"><img src="~/assets/img/update.svg" /><span>@todo.UpdatedDate</span></div>
<a onclick="showDeleteModal(@todo.Id)" title="Delete todo">
<i class="fas fa-trash"></i>
</a>
</div>
</div>
</form>
控制器方法的开始:
[HttpPatch]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit([Bind("Id", "Title", "Description")] Todo todo)
if (ModelState.IsValid)
var matchingTodo = await _context.Todos.FindAsync(todo.Id);
if (matchingTodo != null)
if (GetConnectedUserId() == matchingTodo.UserId)
matchingTodo.Title = todo.Title;
matchingTodo.Description = todo.Description;
matchingTodo.UpdatedDate = DateTime.Now;
_context.Update(matchingTodo);
await _context.SaveChangesAsync();
var todos = GetTodosOfConnectedUser();
var partialView = PartialView("_TodoList", todos);
return partialView;
GetTodosOfConnectedUser 方法(返回属于当前连接的用户的 Todos 的 Enumerable 对象):
private IEnumerable<Todo> GetTodosOfConnectedUser()
return _context.Todos.Where(t => t.UserId == Convert.ToInt32(HttpContext.User.FindFirst("user_id").Value)).OrderByDescending(t => t.UpdatedDate);
还有用于 Ajax 请求的 JS:
$'.todo'.on("change", function (ev)
let form = ev.currentTarget;
editTodo(form);
);
function editTodo(form)
try
$.ajax(
type: 'PATCH',
url: form.action,
data: new FormData(form),
processData: false,
contentType: false,
success: function (res)
$(".error-span").html("");
$('#todos_container').html(res);
,
error: function (err)
console.log(err);
$(".error-span").html("An error occured please try again.");
);
return false;
catch (ex)
console.log(ex);
感谢您的宝贵时间
【问题讨论】:
我在我的 vs 中尝试了你的代码,它工作正常,你可以尝试另一个浏览器并显示更多细节。 遗憾的是,它在 Firefox 中也不起作用:/ 你能提供你的HomePage
,PartialView
和GetTodosOfConnectedUser()
吗?顺便问一下,$('#todos_container').html(res);
是什么?我没有看到任何id=todos_container
。
我正在编辑我的帖子 :) 我没有提供这些信息,因为我真的不认为它会改变任何东西,问题可能来自名称属性的“重复”但如果它可以帮忙,我会发布它们
嗨,GetTodosOfConnectedUser()
中的 UserId
是什么?建议你把这行代码移到_context.Todos.Where(t => t.UserId == Convert.ToInt32(HttpContext.User.FindFirst("user_id").Value)).OrderByDescending(t => t.UpdatedDate);
外面去调试看看返回值是什么
【参考方案1】:
所以,问题很奇怪。就像,真的很奇怪。
我一步一步地跟踪正在发生的事情,一切进展顺利,然后......所有表单都获得相同的输入/文本区域,没有明显的原因。
我相信这是因为我为每个待办事项创建了一个表单,这是一种非常糟糕的做法,可能一开始就没有打算这样做。如果您遇到此问题,只需改变您的处理方式即可。
【讨论】:
正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。【参考方案2】:我展示了我的代码,希望它可以帮助你:
型号
public class Todo
public int Id get; set;
public string Title get; set;
public string Description get; set;
public string UpdatedDate get; set;
查看
@model IEnumerable<TodoApp.Models.Todo>
@
ViewData["Title"] = "Index";
<h1>Index</h1>
<div id="todos_container">
@foreach (Todo todo in Model)
<form class="todo" asp-action="Edit" asp-controller="Todos" data-id="@todo.Id">
<input type="hidden" asp-for="@todo.Id" id="id_@todo.Id" />
<div class="todo-up todo-row">
<textarea autocomplete="off" placeholder="Put the title here..." class="todo-header" asp-for="@todo.Title" id="title_@todo.Id" ></textarea>
<textarea autocomplete="off" placeholder="Put the description here..." class="todo-description" asp-for="@todo.Description" id="decription_@todo.Id" ></textarea>
</div>
<div class="todo-down todo-row">
<div class="todo-validation-row">
<span></span>
<i class="fa-regular fa-check todo-edit" ></i>
<span class="tooltip-text">Saved</span> @*Tooltip for edition*@
</div>
<div class="todo-footer">
<div class="todo-updated"><img src="~/assets/img/update.svg" /><span>@todo.UpdatedDate</span></div>
<a onclick="showDeleteModal(@todo.Id)" title="Delete todo">
<i class="fas fa-trash"></i>
</a>
</div>
</div>
</form>
</div>
@*@section Scripts *@
<script>
$('.todo').on("change", function (ev)
let form = ev.currentTarget;
editTodo(form);
);
function editTodo(form)
try
$.ajax(
type: 'PATCH',
url: '/todoes/Edit',
data: new FormData(form),
processData: false,
contentType: false,
success: function (res)
$(".error-span").html("");
$('#todos_container').html(res);
,
error: function (err)
console.log(err);
$(".error-span").html("An error occured please try again.");
);
return false;
catch (ex)
console.log(ex);
</script>
@**@
动作
[HttpPatch]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit([Bind("Id", "Title", "Description")] Todo todo)
if (ModelState.IsValid)
var matchingTodo = await _context.Todos.FindAsync(todo.Id);
if (matchingTodo != null)
matchingTodo.Title = todo.Title;
matchingTodo.Description = todo.Description;
matchingTodo.UpdatedDate = DateTime.Now.ToString();
_context.Update(matchingTodo);
await _context.SaveChangesAsync();
var todos = GetTodosOfConnectedUser();
var partialView = PartialView("_TodoList", todos);
return partialView;
return BadRequest();
return View(todo);
【讨论】:
以上是关于当更新一个表单(使用 Ajax)时,重新加载表单使它们具有与先前更新的相同的值的主要内容,如果未能解决你的问题,请参考以下文章