@model HelloWorldMvcApp.ViewModel
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
.field-validation-error {
<div class="col-md-6 col-md-offset-3">
@using (Html.BeginForm())
<a href="javascript:void(0)" id="addproject">Add project</a>
@for(int i = 0; i < Model.Projects.Count; i++)
@Html.LabelFor(m => m.Projects[i].Name)
@Html.TextBoxFor(m => m.Projects[i].Name, new { @class="form-control" })
@Html.ValidationMessageFor(m => m.Projects[i].Name)
<input type="hidden" class="projectindex" name="Projects.Index" value="@i" />
<div class="indent stages">
<a href="javascript:void(0)" class="addstage">Add stage</a>
@for(int j = 0; j < Model.Projects[i].Stages.Count; j++)
@Html.LabelFor(m => m.Projects[i].Stages[j].Name)
@Html.TextBoxFor(m => m.Projects[i].Stages[j].Name, new {@class="form-control"})
@Html.ValidationMessageFor(m => m.Projects[i].Stages[j].Name)
<input type="hidden" class="stageindex" name="Projects[@i].Stages.Index" value="@j" />
<div class="indent resources">
<a href="javascript:void(0)" class="addresource">Add resource</a>
@for(int k = 0; k < Model.Projects[i].Stages[j].Resources.Count; k++)
@Html.LabelFor(m => m.Projects[i].Stages[j].Resources[k].Role)
@Html.TextBoxFor(m => m.Projects[i].Stages[j].Resources[k].Role, new {@class="form-control"})
@Html.ValidationMessageFor(m => m.Projects[i].Stages[j].Resources[k].Role)
@Html.LabelFor(m => m.Projects[i].Stages[j].Resources[k].Name)
@Html.TextBoxFor(m => m.Projects[i].Stages[j].Resources[k].Name, new {@class="form-control"})
@Html.ValidationMessageFor(m => m.Projects[i].Stages[j].Resources[k].Name)
<input type="hidden" class="resourceindex" name="Projects[@i].Stages[@j].Resources.Index" value="@j" />
<button type="submit" class="btn btn-success submit">Save</button>
<div id="newproject" class="template">
<label for="Projects_#__Name">Name</label>
<input class="form-control" id="Projects_#__Name" name="Projects[#].Name" type="text" value="">
<span class="field-validation-valid" data-valmsg-for="Projects[#].Name" data-valmsg-replace="true"></span>
<input type="hidden" class="projectindex" name="Projects.Index" value="#">
<div class="indent stages">
<a href="javascript:void(0)" class="addstage">Add stage</a>
<div id="newstage" class="template">
<label for="Projects_#__Stages_%__Name">Name</label>
<input class="form-control" id="Projects_#__Stages_%__Name" name="Projects[#].Stages[%].Name" type="text" value="">
<span class="field-validation-valid" data-valmsg-for="Projects[#].Stages[%].Name" data-valmsg-replace="true"></span>
<input type="hidden" class="stageindex" name="Projects[#].Stages.Index" value="%">
<div class="indent resources">
<a href="javascript:void(0)" class="addresource">Add resource</a>
<div class="resource"></div>
<div id="newresource" class="template">
<label for="Projects_#__Stages_%__Resources_~__Role">Role</label>
<input class="form-control" data-val="true" data-val-required="Please add the role" id="Projects_#__Stages_%__Resources_~__Role" name="Projects[#].Stages[0].Resources[~].Role" type="text" value="">
<span class="field-validation-valid" data-valmsg-for="Projects[0].Stages[%].Resources[~].Role" data-valmsg-replace="true"></span>
<label for="Projects_#__Stages_%__Resources_~__Name">Name</label>
<input class="form-control" data-val="true" data-val-required="Please add the name" id="Projects_#__Stages_%__Resources_~__Name" name="Projects[#].Stages[0].Resources[~].Name" type="text" value="">
<span class="field-validation-valid" data-valmsg-for="Projects[#].Stages[%].Resources[~].Name" data-valmsg-replace="true"></span>
<input type="hidden" class="resourceindex" name="Projects[#].Stages[%].Resources.Index" value="~">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
<script src="//ajax.aspnetcdn.com/ajax/mvc/4.0/jquery.validate.unobtrusive.min.js"></script>
<script type="text/javascript">
var project = $('#newproject');
var stage = $('#newstage');
var resource = $('#newresource');
form.on('click', '.addresource', function() {
var clone = resource.clone();
var projectIndex = $(this).closest('.project').find('.projectindex').val();
clone.html($(clone).html().replace(/#/g, projectIndex));
var stageIndex = $(this).closest('.stage').find('.stageindex').val();
clone.html($(clone).html().replace(/%/g, stageIndex));
var resourceIndex = new Date().getTime();
clone.html($(clone).html().replace(/~/g, resourceIndex));
$(this).closest('.resources').append(clone.html());
form.data('validator', null);
$.validator.unobtrusive.parse(form);
form.on('click', '.addstage', function() {
var clone = stage.clone();
var projectIndex = $(this).closest('.project').find('.projectindex').val();
clone.html($(clone).html().replace(/#/g, projectIndex));
var stageIndex = new Date().getTime();
clone.html($(clone).html().replace(/%/g, stageIndex));
$(this).closest('.stages').append(clone.html());
form.data('validator', null);
$.validator.unobtrusive.parse(form);
$('#addproject').click(function() {
var clone = project.clone();
var projectIndex = new Date().getTime();
clone.html($(clone).html().replace(/#/g, projectIndex));
$('#projects').append(clone.html());
form.data('validator', null);
$.validator.unobtrusive.parse(form);