0

I'm trying to implement dropboxes that can appear prefilled, and can grow dynamically when you press a button. I started with a basic dropdown box implementation that doesn't grow dynamically. This is my controller+DTO code snippet:

public class TaskDTO
{
     public string TaskTemplateName { get; set;}
}

public IActionResult Create()
{
        ViewData["TaskTemplateId"] = new SelectList(_context.TaskTemplates, "Id", "Name");
        return View();
}

public async Task<IActionResult> Create([Bind("Id,TaskTemplateName")] TaskDTO task)
    {
        if (ModelState.IsValid)
        {
            //Do some stuff
        }
        ViewData["TaskTemplateId"] = new SelectList(_context.TaskTemplates, "Id", "Name", task.TaskTemplateName);
        return View(task);
    }

This is my create.cshtml razor code:

<h2>Create</h2>

<h4>TemplateTask</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="TaskTemplateName" class="control-label"></label>
            `  `<select asp-for="TaskTemplateName" class="form-control" asp-items="ViewBag.TaskTemplateId"></select>
            </div>

Then I looked around and found this link that shows how to create dynamic forms that can grow. I tried to combine that idea with dropdown boxes. Based on that tutorial, here's my new DTO+controller code:

public class TaskTemplateDTO
{
    public string TaskTemplateName { get; set; }
}

public class TaskDTO
{
    public List<TaskTemplateDTO> TaskTemplateNames { get; set; }
}


public IActionResult Create()
    {
        var vm = new TaskDTO() { };
        ViewData["TaskTemplateId"] = new SelectList(_context.TaskTemplates, "Id", "Name");
        return View(vm);
    }

public async Task<IActionResult> Create([Bind("Id,TaskName,TaskTemplateNames,ParentTasks,IsBasicTask,EstimatedTime,RequiredResources")] TaskDTO task)
    {
        if (ModelState.IsValid)
        {
            //Do some stuff
        }

        ViewData["TaskTemplateId"] = new SelectList(_context.TaskTemplates, "Id", "Name", task.TaskTemplateNames);
        return View(task);
    }

here's my extra EditorTemplates razor, TaskTemplateDTO.cshtml:

@model Namespace.TaskTemplateDTO

<select asp-for="TaskTemplateName" class="TaskTemplate" asp-items="ViewBag.TaskTemplateId"></select>

This is my create.cshtml razor code:

<h2>Create</h2>

<h4>TemplateTask</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <table class="table table-bordered" id="TaskTemplateTable">
                    <tr>
                        <th>Task Templates</th>
                        <th><button type="button" name="add" id="btn_AddTaskTemplate" class="btn btn-success btn-sm add"><span class="glyphicon glyphicon-plus"></span></button></th>
                        @Html.EditorFor(f => f.TaskTemplateNames)
                    </tr>
                </table>
            </div>
        </form>
    </div>
</div>



@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}

    <script>

        $("#btn_AddTaskTemplate").click(function () {
            var i = $(".TaskTemplate").length;
            var html = '';
            html += '<tr>';
            html += '<td><select type="text" name="TaskTemplateNames[' + i + '].TaskTemplateName" class="TaskTemplate" /></td>';
            html += '<td></td></tr>';
        });

$('#TaskTemplateTable').append(html);
    </script>
}

The code above adds the new dropdowns on click, but the dropdowns aren't prefilled with data, what have I done wrong?

Mantracker
  • 613
  • 10
  • 22
  • Are you adding any – Saharsh Mar 28 '19 at 19:10
  • No, am I supposed to? I didn't know I had to – Mantracker Mar 28 '19 at 19:47
  • I thought that would automatically pick the items to be added for me – Mantracker Mar 28 '19 at 19:48
  • You would need to specify the options you want in your – Saharsh Mar 28 '19 at 20:01
  • I'm trying to add the stored models in ViewData["TaskTemplateId"] = new SelectList(_context.TaskTemplates, "Id", "Name");. So I want all the TaskTemplates from _context.TaskTemplates. Each item in the TaskTemplates list should be an option in the select – Mantracker Mar 28 '19 at 20:14
  • I thought I already built a SelectList and put it in ViewData["TaskTemplateId"], I accessed it in the ViewBag variable on the view side – Mantracker Mar 28 '19 at 20:15

1 Answers1

0

You will need to have the select options that you want in the new controls to be available to your javascript method. There are a few ways to do it, the most straightforward would be to hide it in your html page in a hidden select control.

Your CSHTML:

<h2>Create</h2>

//Added the hidden HTML control here
    @Html.DropDownList("hidden-select", 
        new SelectList((IEnumerable) ViewData["TaskTemplateId"]), 
        null, new Dictionary<string, object>
            {
                { "id", "task-template-names" },
                { "style", "display: none" }
            })
<h4>TemplateTask</h4>
<hr />
<div class="row">
    <div class="col-md-4">
////other things you were doing

This will render in your html as a prepopulated hidden template from which you can build new dropdowns with options on button click.

    $("#btn_AddTaskTemplate").click(function () {
        var i = $(".TaskTemplate").length;
        var html = '';
        html += '<tr>';
        html += '<td><select type="text" name="TaskTemplateNames[' + i + '].TaskTemplateName" class="TaskTemplate">';
        html += document.querySelector("#task-template-names").innerHTML;
        html += '</select></td>';
        html += '<td></td></tr>';
    }); 

I wasn't able to test this code because the setup is beyond my scope here, so you might need to tweak it a little bit. If you encounter any difficult errors, let me know.

Saharsh
  • 750
  • 7
  • 18
  • Hi @Saharsh, I don't have an original prepopulated select. The select statement is dynamically added, whenever a button is pressed, so where should I get this "ID_OF_YOUR_ORIGINAL_PREPOPULATED_SELECT"? – Mantracker Mar 28 '19 at 21:34