0
votes

I have a view which contains a dropdown list and on dropdownlist item being selected I load a partial view. And when the form is submitted I want to be able to get both the values from main view and partial view during form submit. Here is the main view

@model AdminPortal.Areas.Hardware.Models.CreateModule
@{
    ViewBag.Title = "Create Module";
    Layout = "~/Views/shared/_BootstrapLayout.basic.cshtml";
}

@Html.ValidationSummary(true)


<fieldset class="form-horizontal">
    <legend>Add a Module <small>Create</small></legend>
    @using (Html.BeginForm("CreateModule", "Module", new{id="AddModuleForm"}))
    {
        @Html.ValidationSummary(true)
        <div class ="controls">
            <div class="input-block-level">@Html.TextBoxFor(model => model.ModuleId, new {@placeholder = "ModuleID"})</div>
            <br/>
            <div class ="input-block-level" id="selectedModuleTypeName">@Html.DropDownListFor(model => model.SelectedModuleTypeName, Model.TypeNames,"Select Moduletype", new{id = "ModuleList"})</div>

            <br/>
            <div id="partialDiv"></div>
        </div>
         <div class="form-actions" id="buttons">
        <button type="submit" class="btn btn-primary" id="Submit">Save changes</button>
        @Html.ActionLink("Cancel", "ModuleList", null, new { @class = "btn " })
    </div>

    }

</fieldset>
<div>
    @Html.ActionLink("Back to List", "ModuleList")
</div>
<script>
    $("#buttons").hide();
    $("#ModuleList").on("change", function() {
        var modId = $(this).val();
        $.get('@Url.Action("GetModulePropertyName", "Module")', { moduleTypeValue: modId }, function(result) {
            $("#partialDiv").html(result);
        });
        //uncomment following section to check if the partial view is working properly
        /*.done(function() { alert("done"); })
            .fail(function() { alert("fail"); })
            .always(function() { alert("completed"); });*/

    });
        $("#buttons").show();

</script>

and here is the partial view

    @model IEnumerable<string>

    @foreach(var names in Model)
    {
        <div class="input-block-level">@Html.TextBoxFor(m=>names, new{Value="", placeholder=names})</div>
        <br/>
    }

Here is my model

public class CreateModule
    {
        //Empty form to handle form serialization
        public CreateModule()
        {
        }

        [Required]
        public string ModuleId { get; set; }

        [DataType(DataType.DateTime)]
        public DateTime DateEntered { get; set; }

        [Required]
        public string SelectedModuleTypeName { get; set; }
        public IEnumerable<SelectListItem> TypeNames { get; set; }

        public List<Property> Properties { get; set; }
    }

public class Property
    {
        public string Name { get; set; }
        public string Value { get; set; }
    }

Here is the method that script in main view forwards to

[HttpGet]
        public ActionResult GetModulePropertyName(string moduleTypeValue)
        {
            var moduleKindId = _repository.GetModuleKindId(moduleTypeValue);
            var modulePropertyNames = _repository.GetModuleKindPropertyNames(moduleTypeValue);
            return PartialView("GetModulePropertyName",modulePropertyNames);
        }

and finally here is httppost method for the main view

[HttpPost]
        public ActionResult CreateModule(CreateModule moduleV)
        {
            var module = new Module
                {
                    ModuleTypeId = Convert.ToInt64(moduleV.SelectedModuleTypeName),
                    ModuleId = moduleV.ModuleId,
                    DateEntered = moduleV.DateEntered,


                };
            if (ModelState.IsValid)
            {
               _repository.AddModule(module);
                Success("Module added successfully!");
                return RedirectToAction("ModuleList", "Module", new {area = "Hardware"});
            }


                Error("Something went wrong!");
                return RedirectToAction("CreateModule", "Module", new { area = "Hardware" });

        }

Current situation: When the form is posted, the properties value of the model that is being passed via partial view is null. I get other values, like typename, Module ID.

What I'd want: I also want to get the value of properties that is being passed via partial view.

3

3 Answers

1
votes

You don't have any input field for the Properties property anywhere in your form. So it will always be null. That's normal.

Here's how you could proceed. Start by setting the correct navigational property so that the helper generates correct names of the corresponding input fields.

Also make sure that you are passing an IEnumerable<Property> model to the partial if you want to be able to get them back correctly:

[HttpGet]
public ActionResult GetModulePropertyName(string moduleTypeValue)
{
    var moduleKindId = _repository.GetModuleKindId(moduleTypeValue);
    IList<Property> model = ...
    return PartialView("GetModulePropertyName", model.ToList());
}

and in your partial view use an editor template:

@model IList<Property>
@{
    // This indicates the current navigational context to the helpers
    ViewData.TemplateInfo.HtmlFieldPrefix = "Properties";
}

@Html.EditorForModel()

and the last step is to define a custom editor template for the Property class: ~/Views/Shared/EditorTemplates/Property.cshtml (note that the name and location of the template is important)

@model Property
<div class="input-block-level">
    @Html.HiddenFor(m => m.Name)
    @Html.TextBoxFor(m => m.Value, new { placeholder = Model.Name })
</div>
<br />
0
votes

Try using the

List<Property> 

as a model in your partial view and pass the CreateModule.Properties as model from your View

0
votes

The problem is model binder can not figure out there

@Html.TextBoxFor(m=>names, new{Value="", placeholder=names})

belongs to as the "names" is not a property on your model class. If you need to bind to the CreateModule.Properties you need to change the partial view to emit textboxes with aproprate names, like this one:

 @model IEnumerable<string>
@
{
 int i=0;
}
    @foreach(var names in Model)
    {
        <div class="input-block-level">@Html.TextBox("Properties[" + i + "].Value")</div>
        <br/>
    }