MVC批量更新,使用jQuery Template
在"MVC批量更新,可验证并解决集合元素不连续控制器接收不完全的问题"中,当点击"添加"按钮的时候,通过部分视图,在界面上添加新行。本篇体验使用jQuery Template,在界面上添加新行。
□ 思路
→引用jQuery Template所需要的js文件:jquery.tmpl.min.js
→在<script type="text/x-jquery-tmpl" id="movieTemplate"></script>中生成模版内容,里面包含占位符
→点击添加按钮的时候,把模版内容追加到界面上,并给占位符赋值
□ jQuery Template的内容大致是这样:
<script type="text/x-jquery-tmpl" id="movieTemplate">
<li style="padding-bottom:15px">
<input autocomplete="off" name="FavouriteMovies.Index" type="hidden" value="${index}" />
<img src="/Content/images/draggable-icon.png" style="cursor: move" alt=""/>
<label>Title</label>
<input name="FavouriteMovies[${index}].Title" type="text" value="" />
<label>Rating</label>
<input name="FavouriteMovies[${index}].Rating" type="text" value="0" />
<a href="#" onclick="$(this).parent().remove();">Delete</a>
</li>
</script>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
为了得到以上内容,由帮助类方法获得:
<script type="text/x-jquery-tmpl" id="movieTemplate">
@Html.CollectionItemJQueryTemplate("MovieEntryEditor", new Movie())
</script>
帮助类CollectionEditingHtmlExtensions:
模版内容同样是通过MovieEntryEditor.cshtml这个部分视图生成的,只不过生成的内容中包含了占位符。
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace VariableCollection.Extension
{
public static class CollectionEditingHtmlExtensions
{
/// <summary>
/// 目标是生成如下格式
///<input autocomplete="off" name="FavouriteMovies.Index" type="hidden" value="6d85a95b-1dee-4175-bfae-73fad6a3763b" />
///<label>Title</label>
///<input class="text-box single-line" name="FavouriteMovies[6d85a95b-1dee-4175-bfae-73fad6a3763b].Title" type="text" value="Movie 1" />
///<span class="field-validation-valid"></span>
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <param name="html"></param>
/// <param name="collectionName">集合属性的名称</param>
/// <returns></returns>
public static IDisposable BeginCollectionItem<TModel>(this HtmlHelper<TModel> html, string collectionName)
{
if (string.IsNullOrEmpty(collectionName))
{
throw new ArgumentException("collectionName is null or empty","collectionName");
}
string collectionIndexFieldName = String.Format("{0}.Index", collectionName);//FavouriteMovies.Index
string itemIndex = null;
if (html.ViewData.ContainsKey(JQueryTemplatingEnabledKey))
{
itemIndex = "${index}";
}
else
{
itemIndex = GetCollectionItemIndex(collectionIndexFieldName);
}
//比如,FavouriteMovies[6d85a95b-1dee-4175-bfae-73fad6a3763b]
string collectionItemName = string.Format("{0}[{1}]", collectionName, itemIndex);
TagBuilder indexField = new TagBuilder("input");
indexField.MergeAttributes(new Dictionary<string, string>() {
{ "name", String.Format("{0}.Index", collectionName) }, //name="FavouriteMovies.Index"
{ "value", itemIndex },//value="6d85a95b-1dee-4175-bfae-73fad6a3763b"
{ "type", "hidden" },
{ "autocomplete", "off" }
});
html.ViewContext.Writer.WriteLine(indexField.ToString(TagRenderMode.SelfClosing));
return new CollectionItemNamePrefixScope(html.ViewData.TemplateInfo, collectionItemName);
}
private class CollectionItemNamePrefixScope : IDisposable
{
private readonly TemplateInfo _templateInfo;
private readonly string _previousPrefix;
public CollectionItemNamePrefixScope(TemplateInfo templateInfo, string collectionItemName)
{
this._templateInfo = templateInfo;
_previousPrefix = templateInfo.HtmlFieldPrefix;
templateInfo.HtmlFieldPrefix = collectionItemName;
}
public void Dispose()
{
_templateInfo.HtmlFieldPrefix = _previousPrefix;
}
}
/// <summary>
/// 以FavouriteMovies.Index为键,把Guid字符串存放在上下文中
/// 如果是添加进入部分视图,就直接生成一个Guid字符串
/// 如果是更新,为了保持和ModelState的一致,就遍历原先的Guid
/// </summary>
/// <param name="collectionIndexFieldName">FavouriteMovies.Index</param>
/// <returns>返回Guid字符串</returns>
private static string GetCollectionItemIndex(string collectionIndexFieldName)
{
Queue<string> previousIndices = (Queue<string>)HttpContext.Current.Items[collectionIndexFieldName];
if (previousIndices == null)
{
HttpContext.Current.Items[collectionIndexFieldName] = previousIndices = new Queue<string>();
string previousIndicesValues = HttpContext.Current.Request[collectionIndexFieldName];
if (!string.IsNullOrWhiteSpace(previousIndicesValues))
{
foreach (string index in previousIndicesValues.Split(','))
{
previousIndices.Enqueue(index);
}
}
}
return previousIndices.Count > 0 ? previousIndices.Dequeue() : Guid.NewGuid().ToString();
}
private const string JQueryTemplatingEnabledKey = "__BeginCollectionItem_jQuery";
public static MvcHtmlString CollectionItemJQueryTemplate<TModel, TCollectionItem>(this HtmlHelper<TModel> html,
string partialViewName,
TCollectionItem modelDefaultValues)
{
ViewDataDictionary<TCollectionItem> viewData = new ViewDataDictionary<TCollectionItem>(modelDefaultValues);
viewData.Add(JQueryTemplatingEnabledKey, true);
return html.Partial(partialViewName, modelDefaultValues, viewData);
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
□ MovieEntryEditor.cshtm部分视图与上篇相同
@using VariableCollection.Extension
@model VariableCollection.Models.Movie
<li style="padding-bottom: 15px;">
@using (Html.BeginCollectionItem("FavouriteMovies"))
{
<img src="@Url.Content("~/Content/images/draggable-icon.png")" style="cursor: move" alt=""/>
@Html.LabelFor(model => model.Title)
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
@Html.LabelFor(model => model.Rating)
@Html.EditorFor(model => model.Rating)
@Html.ValidationMessageFor(model => model.Rating)
<a href="#" onclick=" $(this).parent().remove(); ">删除行</a>
}
</li>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
□ HomeController
public ActionResult EditJqueryTemplate()
{
return View(CurrentUser);
}
[HttpPost]
public ActionResult EditJqueryTemplate(User user)
{
if (!this.ModelState.IsValid)
{
return View(user);
}
CurrentUser = user;
return RedirectToAction("Display");
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
□ EditJqueryTemplate.cshtml完整代码如下:
@using VariableCollection.Extension
@using VariableCollection.Models
@model VariableCollection.Models.User
@{
ViewBag.Title = "EditJqueryTemplate";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>EditJqueryTemplate</h2>
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>最喜欢看的电影</legend>
@Html.HiddenFor(model => model.Id)
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
</fieldset>
<fieldset>
<legend>最喜欢看的电影</legend>
@if (Model.FavouriteMovies == null || Model.FavouriteMovies.Count == 0)
{
<p>没有喜欢看的电影~~</p>
}
<ul id="movieEditor" style="list-style-type: none">
@if (Model.FavouriteMovies != null)
{
foreach (Movie movie in Model.FavouriteMovies)
{
Html.RenderPartial("MovieEntryEditor", movie);
}
}
</ul>
<a id="addAnother" href="#" >添加</a>
</fieldset>
<p>
<input type="submit" value="提交" />
</p>
}
@section scripts
{
<script src="~/Scripts/jquery.tmpl.min.js"></script>
<script type="text/x-jquery-tmpl" id="movieTemplate">
@Html.CollectionItemJQueryTemplate("MovieEntryEditor", new Movie())
</script>
<script type="text/javascript">
$(function () {
$("#movieEditor").sortable();
$('#addAnother').click(function() {
viewModel.addNew();
});
});
var viewModel = {
addNew: function () {
$("#movieEditor").append($("#movieTemplate").tmpl({ index: viewModel._generateGuid() }));
},
_generateGuid: function () {
// Source: http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/105074#105074
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
};
</script>
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
参考资料:
※ Editing Variable Length Reorderable Collections in ASP.NET MVC – Part 2: jQuery Templates
MVC批量更新,使用jQuery Template的更多相关文章
- MVC批量更新,可验证并解决集合元素不连续控制器接收不完全的问题
在"MVC批量添加,增加一条记录的同时添加N条集合属性所对应的个体"中,有2个问题待解决: 1.由jquery动态生成了表单元素,但不能实施验证. 2.一旦集合元素不连续,控制器就 ...
- Spring批量更新batchUpdate提交和Hibernate批量更新executeUpdate
1:先看hibernate的批量更新处理. 版本背景:hibernate 5.0.8 applicationContext.xml 配置清单: <?xml version="1.0&q ...
- EF结合SqlBulkCopy实现高效的批量数据插入 |EF插件EntityFramework.Extended实现批量更新和删除
原文链接:http://blog.csdn.net/fanbin168/article/details/51485969 批量插入 (17597条数据批量插入耗时1.7秒) using Sys ...
- mongodb 批量更新 数组的键操作的文件
persons该文件的数据如下面的: > db.persons.find() { "_id" : 2, "name" : 2 } { "_id& ...
- mongodb批量更新操作文档的数组键
persons文档的数据如下: > db.persons.find(){ "_id" : 2, "name" : 2 }{ "_id" ...
- jQuery.template.js 简单使用
之前看了一篇文章<我们为什么要尝试前后端分离>,深有同感,并有了下面的评论: 我最近也和前端同事在讨论这个问题,比如有时候前端写好页面给后端了,然后后端把这些页面拆分成很多的 views, ...
- SQL批量更新 关系表更新
很多人在做数据的批量更新时..如果更新的内容是从其他表查出来的..很容易这么写.. UPDATE TABLE1 SET COLUMN1=(SELECT SUM(SOMETHING) FROM TABL ...
- SQL 将2张不相关的表拼接成2列,批量更新至另一张表
update SO_Master set LotteryNo=t2.LotteryNo,UpdateTime=GETDATE() --select sm.LotteryNo,sm.SysNo,t2.L ...
- [PDO绑定参数]使用PHP的PDO扩展进行批量更新操作
最近有一个批量更新数据库表中某几个字段的需求,在做这个需求的时候,使用了PDO做参数绑定,其中遇到了一个坑. 方案选择 笔者已知的做批量更新有以下几种方案: 1.逐条更新 这种是最简单的方案,但无疑也 ...
随机推荐
- **PHP转义Json里的特殊字符的函数
http://www.banghui.org/11332.html 在给一个 App 做 API,从服务器端的 MySQL 取出数据,然后生成 JSON.数据中有个字段叫 content,里面保存了文 ...
- Metronic4.7.5 下载 HTML5 UI后台管理框架
Metronic 是一套精美的响应式后台管理模板,基于强大的 Twitter Bootstrap 3.3.4 框架实现.Metronic 拥有简洁优雅的 Metro UI 风格界面,6 种颜色可选,7 ...
- CCF CSP 201604-3 路径解析
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201604-3 路径解析 问题描述 在操作系统中,数据通常以文件的形式存储在文件系统中.文件系 ...
- IE6 验证码刷新失败显示空白解决办法
原因:点击a标签看不清?换图片 结果验证码显示的空白! 解决办法:在对应的点击事件最后加上return false 即可解决问题. 下面是HTML源码: <p class="regis ...
- 【ARC066】F - Contest with Drinks Hard
题解 我写的斜率维护,放弃了我最擅长的叉积维护,然后发现叉积维护也不会爆long long哦-- 一写斜率维护我的代码就会莫名变长而且难写--行吧 我们看这题 推了推式子,发现这是个斜率的式子,但是斜 ...
- 20169211《Linux内核原理及分析》第十二周作业
Collabtive 系统 SQL 注入实验 实验介绍 SQL注入漏洞的代码注入技术,利用web应用程序和数据库服务器之间的接口.通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串, ...
- DDR3调试记录
FPGA采集视频数据并写到DDR3,然后从DDR3读出并送给显示终端显示.不能稳定显示.但用FPGA内部逻辑产生color bar写到DDR3后读出来显示正常.因此DDR3部分逻辑没有问题 ...
- Java 关于集合框架那点事儿
1.引入集合框架 采用数组存在的一些缺陷: 1.数组长度固定不变,不能很好地适应元素数量动态变化的情况. 2.可通过数组名.length获取数组的长度,却无法直接获取数组中真实存储的个数. ...
- JAVA 获取分行符
public static final String CR_LF = System.getProperty("os.name").startsWith("Windows& ...
- golang make()的第三个参数
golang分配内存有一个make函数,该函数第一个参数是类型,第二个参数是分配的空间,第三个参数是预留分配空间,前两个参数都很好理解, 对于第三个参数,例如a:=make([]int, 5, 10) ...