我的MVC应用程序的用户可以创建新的“事件”。每个“事件”都有一些属性,例如名称,位置等。每个“事件”也都有一个或多个“时间范围”。当用户想要创建一个新的“事件”时,AddEvent视图默认为1个时间范围,但是用户可以添加额外的时间范围。视图看起来像这样:
Create view http://users.telenet.be/evdes/Capture.PNG
我可以结合使用Taghelpers和Jquery来完成这项工作。
型号:
public class Event
{
public Event()
{
Timeframes = new List<TimeFrame>();
Participants = new List<Participant>();
}
public int Id { get; set; }
[Required]
[Display(Name="Event Name")]
[MaxLength(50, ErrorMessage ="The name you've entered is too long")]
public string Name { get; set; }
[Required]
[MaxLength(500, ErrorMessage = "The description you've entered is too long")]
public string Description { get; set; }
[Required]
[Range(1,int.MaxValue, ErrorMessage ="Enter a valid number larger than 0")]
public int WantedAmountOfParticipants { get; set; }
public List<TimeFrame> Timeframes { get; set; }
public Location Location { get; set; }
public List<Participant> Participants { get; set; }
public bool IsCancelled { get; set; }
}
查看:
<form method="post">
<partial name="Partials/_EventBasicInputDetails" model="Model" />
<div id="TimeFramesToAdd">
@for (var i = 0; i < Model.Timeframes.Count; i++)
{
<div class="timeframes" id="Timeframe_@i">
<label asp-for="Timeframes[i].EventDate"></label>
<input asp-for="Timeframes[i].EventDate" min="@DateTime.Today" />
<span asp-validation-for="Timeframes[i].EventDate"></span>
<label asp-for="Timeframes[i].Starttime"></label>
<input asp-for="Timeframes[i].Starttime" min="0" max="24" />
<span asp-validation-for="Timeframes[i].Starttime"></span>
<label asp-for="Timeframes[i].Endtime"></label>
<input asp-for="Timeframes[i].Endtime" min="0" max="24" />
<span asp-validation-for="Timeframes[i].Endtime"></span>
<button type="button" class="DeleteTimeframeButton" data-id="@i">Delete Timeframe</button>
</div>
}
</div>
<a href="#" id="addTimeframe">Add Timeframe</a>
<div>
<a asp-action="AllUpcomingEvents">Cancel</a>
<input type="submit" name="Add" value="Add" />
</div>
</form>
jQuery
//Add empty timeframes when adding event
$("#addTimeframe").click(function (e) {
e.preventDefault();
//Set counter for dynamical generation of ID attributes for modelbinding
var i = $(".timeframes").length;
//Html element to be added
var newTimeframe = `<div class="timeframes" id="Timeframe_` + i + `">
<label for= "Timeframes_` + i + `__EventDate" > Event Date</label >
<input type="date" data-val="true" data-val-required="The Event Date field is required." id="Timeframes_` + i + `__EventDate" name="Timeframes[` + i + `].EventDate" />
<span class="field-validation-valid" data-valmsg-for="Timeframes[` + i + `].EventDate" data-valmsg-replace="true"></span>
<label for="Timeframes_` + i + `__Starttime">Start</label>
<input min="0" max="24" type="number" data-val="true" data-val-range="Invalid hour" data-val-range-max="24" data-val-range-min="0" data-val-required="The Start field is required." id="Timeframes_` + i + `__Starttime" name="Timeframes[` + i + `].Starttime" value="0" />
<span class="field-validation-valid" data-valmsg-for="Timeframes[` + i + `].Starttime" data-valmsg-replace="true"></span>
<label for="Timeframes_` + i + `__Endtime">End</label>
<input min="0" max="24" type="number" data-val="true" data-val-range="Invalid hour" data-val-range-max="24" data-val-range-min="0" data-val-required="The End field is required." id="Timeframes_` + i + `__Endtime" name="Timeframes[` + i + `].Endtime" value="0" />
<span class="field-validation-valid" data-valmsg-for="Timeframes[` + i + `].Endtime" data-valmsg-replace="true"></span>
<button type="button" id="DeleteTimeframeButton_` + i + `" class="DeleteTimeframeButton" data-id=` + i + `>Delete Timeframe</button>
</div>`
//Set click event on generated button
$("#TimeFramesToAdd").append(newTimeframe);
var button = $("#DeleteTimeframeButton_" + i);
button.click(removeTimeframe);
});
//***Helper Functions***
function removeTimeframe() {
if ($(".timeframes").length > 1) {
var timeframeToRemove = "#Timeframe_" + $(this).data('id');
$(timeframeToRemove).remove();
}
}
这很好用,但是请注意用于创建新时间范围的HTML元素的巨大魔术字符串。这似乎不是解决此问题的最佳方法。有什么建议吗?
答案 0 :(得分:0)
无需使用太多魔术字符串即可通过jQuery生成TimeFrame元素。最简单的方法是重用服务器端函数以生成部分形式:
首先,创建/Views/Shared/_TimeFrames.cshtml
的局部视图:
@model App.Models.Event
@{
// add a blank one for rendering
if(Model.Timeframes==null){
Model.Timeframes= new List<TimeFrame>(){};
}
if(Model.Timeframes.Count==0){
Model.Timeframes.Add(new TimeFrame());
}
var i = 0;
}
<div class="timeframes">
<label asp-for= "@Model.Timeframes[i].EventDate" ></label>
<input asp-for= "@Model.Timeframes[i].EventDate" />
<span class="field-validation-valid" asp-validation-for="@Model.Timeframes[i].EventDate" ></span>
<label asp-for="@Model.Timeframes[i].Starttime">Start</label>
<input asp-for="@Model.Timeframes[i].Starttime" />
<span class="field-validation-valid" asp-validation-for="@Model.Timeframes[i].Starttime" ></span>
<label asp-for="@Model.Timeframes[i].Endtime">End</label>
<input asp-for="@Model.Timeframes[i].Endtime" />
<span class="field-validation-valid" asp-validation-for="@Model.Timeframes[i].Endtime"></span>
<button type="button" class="DeleteTimeframeButton" onclick="$(this).parent().remove();return false;"> Delete Timeframe</button>
</div>
如您所见,我们现在能够以强类型的方式生成TimeFrame
的字段。名称,ID,DisplayName和验证规则是自动生成的。您可以自由添加自己的规则。
现在我们可以将TimeFrame
渲染到客户端模板中,并在有人单击“ #addTimeframe”按钮时重新使用它来生成TimeFrame
html元素:
<script id="timeframe-template-rendered" type="text/plain" >
@Html.Partial("/Views/Shared/_TimeFrames.cshtml",new App.Models.Event())
</script>
<!-- a helper that renders the client side template -->
<script>
function partialFormRenderer(templateStr,index=0){
var itemTpl = templateStr
.replace("_"+index+"__","${i}")
.split(/\$\{(.+?)\}/g);
return function render(model){
return itemTpl.map((token,idx)=> idx%2 ===0 ? token : model[token]).join('');
};
}
// create a render function with the client side template
var render = partialFormRenderer(document.getElementById("timeframe-template-rendered").innerHTML);
</script>
<script>
$("#addTimeframe").click(function (e) {
e.preventDefault();
var i = $(".timeframes").length;
var newTimeframe = render(i);
$("#TimeFramesToAdd").append(newTimeframe);
});
</script>