0

I'm trying to dynamically add items to a list and make these items show up in my controller after submitting, but right now I don't even get the existing list-items to show up.

I'm not 100% what the issue is, but it seems to have something to do with the partial view that is rendered for each item.

ViewModels:

public class UserGroupVM
{
    public int Id { get; set; }
    [Required]
    [Display(Name = "Usergruppe")]
    public string Name { get; set; }
    [Display(Name = "Beschreibung")]
    public string Description { get; set; }
    [Required]
    public Boolean IsGlobal { get; set; }
    public List<Employee_UserGroupVM> Employees { get; set; }
}

public class Employee_UserGroupVM
{
    public int Id { get; set; }
    [Display(Name = "Kennung")]
    public string SamAccountName { get; set; }
    [Display(Name = "Name")]
    public string LastnameFirstName { get; set; }
    [Display(Name = "Admin")]
    public bool IsAdmin { get; set; }
}

Form-View:

@model DAKCrmImport.Web.Models.UserGroupVM

@{
    ViewBag.Title = "_UserGroup";
}

@using (Html.BeginForm("Save", "UserGroup", FormMethod.Post, new { Id = "form-usergroup-add", novalidate = "false" }))
{
    <fieldset>
        <div class="container-form-clear">
            <a class='button form-clear' title='Formular leeren'>button clear</a>
        </div>
        @Html.HiddenFor(model => model.Id)
        @Html.LabelFor(model => model.Name, new { @class = "label req" })
        @Html.TextBoxFor(model => model.Name, new { @class = "input"})
        @Html.LabelFor(model => model.Description, new { @class = "label" })
        @Html.TextAreaFor(model => model.Description, new { @class = "input", rows = "3", cols = "25" })
        <br />

        <a class='button form-add' title='MA-Berechtigung hinzufügen' id="bt-employee-add">button employee-add</a>
        @for (int i = 0; i < Model.Employees.Count(); i++)
        {
            @Html.EditorFor(m => m.Employees[i]);
        }

        <input type="submit" name="submit" class="submit form-button" value="Speichern" id="bt-submit-usergroup" />
    </fieldset>
}

Partial View:

@model DAKCrmImport.Web.Models.Employee_UserGroupVM

@{
    ViewBag.Title = "_EmployeeList";
}
<div class="div-employee-add">
    <div class="container-right">
        <a class="button form-remove-employee" title="MA entfernen" id="bt-employee-delete">button ma-remove</a>
    </div>
    <div class="container-left">
        @Html.LabelFor(model => model.SamAccountName)
        @Html.TextBoxFor(model => model.SamAccountName, new { @class = "textbox-samaccountname" })
        @Html.TextBoxFor(model => model.LastnameFirstName, new { @class = "textbox-lastnamefirstname", disabled = "disabled" })
        @Html.LabelFor(model => model.IsAdmin)
        @Html.CheckBoxFor(model => model.IsAdmin, new { @class = "checkbox-isadmin" })
    </div>
</div>

Controller:

public virtual ActionResult BlankEmployeeRow()
{
    return PartialView("EditorTemplates/Employee_UserGroupVM", new Employee_UserGroupVM());
}
public virtual ActionResult Save(UserGroupVM usergroup)
{
    return null;
}

The only thing I noticed so far is that existing items Employees appear in the controller if I don't use a partial view and display its variables through indexing. Because I can't do any indexing in the partial view itself it doesn't work now. I have no clue how to fix it though and it's questionable whether new or edited items will turn up anyways.

I'd really appreciate a little help.

P.S. I know how to read the model via jQuery, but I want to use MVC's native form submit method wihout additional code.

[Update] I made an EditorTemplate out of my partial view and now the existring Employees get submitted, but additional employees still don't. Even though they appear in the markup ...

Adding new items via jquery/partial view:

$(document).on('click', '#bt-employee-add', function () {
    var lastDiv = $("[class~='div-employee-add']").first();
    var lastTextBox = $(lastDiv).find("[class~='textbox-lastnamefirstname']");

    var url = $("#EmployeeAdd").data('request-url');
    var params = null;

    if (lastTextBox.val() == "") {
        //Notification
    } else {
        $(getJSONfromController(url, params, null, true)).insertBefore($(".div-employee-add").first());
    }
});
OhSnap
  • 376
  • 2
  • 10
  • 30
  • 1
    for first add an [HttpPost] attribute to your Save action – Suren Srapyan Dec 02 '15 at 12:30
  • What does your controller look like? – Niklas Dec 02 '15 at 12:31
  • The two Actions I use with the Controller are already there. I use "Save" for the submit and BlankEmployeeRow to add a blank Employee. – OhSnap Dec 02 '15 at 12:35
  • btw HttpPost wouldn't help me solving this problem at all. Hence your comment is somewhat unproductive .. – OhSnap Dec 02 '15 at 12:39
  • http://stackoverflow.com/questions/27234463/mvc-razor-html-partial-sub-model This can probably help you. – Robin Dorbell Dec 02 '15 at 12:40
  • 1
    Firstly you do not use `EditorFor()` in a loop - its just `@Html.EditorFor(m => m.Employees)`- the `EditorFor()` method accepts `IEnumerable` and generates the correct hml for each item in the collection. But if your wanting to dynamically add a new `Employee_UserGroupVM` then refer to the answers [here](http://stackoverflow.com/questions/29161481/post-a-form-array-without-successful/29161796#29161796) and [here](http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) –  Dec 03 '15 at 00:03
  • Doesn't seem to work for me .. I have no clue why, but @Html.EditorFor(m => m.Employees) only shows the Id's of the items in the IEnumerable. -.- – OhSnap Dec 03 '15 at 05:26
  • You have an issue in your jquery. Here is a test that you can do to confirm that. Add 5 mock employees (hard code them in your controller) to your employee list. Then check the html source and try to understand how they appear in your view. Then add a new employee using your button click. Then compare the html source again. You will see it has just duplicated the 5th employee's elements. So your controller will not recognise the newly added employee. Can you change your jquery to fix that? Let us know if you can't. – Kosala W Dec 04 '15 at 00:29

2 Answers2

1

Try this:

@Html.Partial("_EmployeeList", Model.Employees, new ViewDataDictionary
{
    TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "Employees" }
})

The problem is the partial doesn't know the name of the list, so you have to specify it explicitly.

Robin Dorbell
  • 1,569
  • 1
  • 13
  • 26
  • This is the right way, but Im not parsing a list to the partial-view but a single item. It does however work with EditorFor. At least as long as I don't reference the partial view "_EmployeeList" -.- – OhSnap Dec 02 '15 at 13:00
  • Ok .. using EditorFor now, but adding new items doesn't work. They do appear in the Markup, but they don't get submitted with the rest of the data... which is really annoying – OhSnap Dec 02 '15 at 13:21
  • How are you adding new items then? jQuery? Are you giving them the correct `name=`? – Robin Dorbell Dec 02 '15 at 13:35
0

When you're using a simple ViewModel your data is not going to be dynamically updated as your page is not going to poll your server. It will only get the new data on refresh.

You'll either have to use a timer to poll or look into angular, knockout or ember.

RekaB
  • 438
  • 5
  • 14