简体   繁体   中英

How can I add model list values dynamically in MVC?

I have a model list and I used that model to display values into a table. On that table if I add a new row means it is adding the new row but in the model list it is not binding.

My model:

public class ApplicationInfo
{
    [Display(Name = "Business Unit")]
    [Required(ErrorMessage = "Business Unit is required")]
    public int biz_unit_key { get; set; }

    [Display(Name = "Application Short Code")]
    [Required(ErrorMessage = "Application Short Code is required")]
    [StringLength(10, ErrorMessage = "Application Short Code length should be less than or equal to 100")]
    public string app_short_code { get; set; }

    [Display(Name = "Application Name")]
    [Required(ErrorMessage = "Application Name is required")]
    [StringLength(10, ErrorMessage = "Application Name length should be less than or equal to 100")]
    public string app_name { get; set; }

    public List<ApplicationAccessRoles> ApplAccessRoleInfo { get; set; }      
    }

    public class ApplicationAccessRoles
    {
        public int app_access_role_key { get; set; }
        public int app_key { get; set; }
        public string access_role { get; set; }
        public bool inactive { get; set; }
    }

My view:

<table id="RolesDetails" cellpadding="0" cellspacing="0" class="data_table">
    <tr class="dataheader">
        <td class="width5">
            &nbsp;
            @Html.HiddenFor(m => m.app_access_role_key)
        </td>
        <td class="width200">
            Access Roles Name
        </td>
        <td class="width10">
            Inactive
        </td>                         
    </tr>

    @if (Model.ApplAccessRoleInfo.Count!= 0) // class-2 for populate data in table 
    {
        var chk = Model.ApplAccessRoleInfo.Count;
        for (int a = 0; a < Model.ApplAccessRoleInfo.Count; a++)
        {
            <tr class="exp_col_header top_border_nil">
                @if ((chk - 1) == a)
                { 
                    <td><a href="#" class="gridexpand" rel="1"></a></td> @* for add new row *@
                }
                else
                {
                    <td></td>
                }

                <td>
                    @Html.HiddenFor(m => m.ApplAccessRoleInfo[a].app_access_role_key)
                    @Html.EditorFor(m => m.ApplAccessRoleInfo[a].access_role)
                </td>
                <td>
                    @Html.CheckBox("ApplTeamAccessInfo[" + a.ToString() + "].inactive", false, new { @class = "check-box" })
                </td>
            </tr>
        }
    }
    else
    {
        <tr class="exp_col_header top_border_nil">
            <td>
                <a href="#" class="gridexpand" rel="1"></a> @* for add new row *@    
            </td>
            <td>
                @*@Html.EditorFor(model => model.access_role)*@
                @*@Html.EditorFor(m => m.ApplAccessRoleInfo[0].access_role)*@
                @Html.EditorFor(model=>model.access_role)
            </td>
            <td>
                @Html.CheckBoxFor(model => model.inactive)
            </td>
        </tr>                         
    }
</table>

<table id="newrow" style="display:none">
    <tr class="exp_col_header top_border_nil">
        <td>
            <a href="#" class="gridexpand" rel="1"></a>
        </td>
        <td>
            <input data-val="true" data-val-number="The field app_access_role_key must be a number." data-val-required="The app_access_role_key field is required." name="ApplAccessRoleInfo[#].app_access_role_key" type="hidden" value="#">
            <input class="text-box single-line" name="ApplAccessRoleInfo[#].access_role" type="text" value="#">
        </td>
        <td>
            <input class="check-box" name="ApplTeamAccessInfo[#].inactive" type="checkbox" value="false"><input name="ApplTeamAccessInfo[#].inactive" type="hidden" value="false">
        </td>
    </tr>
</table>

My jQuery used to add new row to the table:

$(".gridexpand").click(function (event) {
    @*
        @Html.HiddenFor(m => m.ApplTeamAccessInfo[a].app_access_role_key)
        @Html.EditorFor(m => m.ApplTeamAccessInfo[a].access_role) 

        <table id="RolesDetails" cellpadding="0" cellspacing="0" class="data_table"> 
    *@

    var tablebody = $('#RolesDetails'); // modify to suit your id
    var newrow = $('#newrow');
    var index = 0; // unique indexer
    var clone = newrow.clone(); // clone the new row

    alert("new row");
    clone.html($(clone).html().replace(/#/g, index)); // update the indexer of the clone
    var row = clone.find('tr');
    tablebody.append(row); 
});

my Controller

  public ActionResult Index(int? id)
        {
        ApplicationInfo AppInfo = new ApplicationInfo();

        List<ApplicationAccessRoles> access = new List<ApplicationAccessRoles>();
        mas_app_access_roles roles;


        mas_apps application;
        UserInfo oUser = (UserInfo)Session["UserInfo"];
        if (id == null || id == 0)
        {
            application = new mas_apps();
            roles = new mas_app_access_roles();
            application.Applications = db.mas_apps.ToList();
        }
        else
        {
            application = db.mas_apps.Find(id);

                roles = db.mas_app_access_roles.Find(id);
                AppInfo.app_access_role_key = roles.app_access_role_key;
                AppInfo.app_key = roles.app_key;
                //AppInfo.access_role = <IEnumerable>roles.access_role;
                AppInfo.inactive = roles.inactive;
                AppInfo.created_by = roles.created_by;
                AppInfo.created_date = roles.created_date;
                AppInfo.last_modified_by = roles.last_modified_by;
                AppInfo.last_modified_date = roles.last_modified_date;

        var main = (from a in db.mas_app_access_roles
                    where a.app_key == AppInfo.app_key
                    select new ApplicationAccessRoles
                    {

                        app_access_role_key = a.app_access_role_key,
                        access_role = a.access_role,
                        inactive = a.inactive,
                    }
                    ).ToList();
        access = main;
        AppInfo.ApplAccessRoleInfo = access;
        ViewBag.check = access;
        return View(AppInfo);
    }

and for saving the table after edit

if (ModelState.IsValid)
        {
            UserInfo oUser = (UserInfo)Session["UserInfo"];
            if (app.app_key == 0)
            {
                mas_apps appInfo = new mas_apps();
                appInfo.app_key = 0;
                appInfo.biz_unit_key = app.biz_unit_key;
                appInfo.app_short_code = app.app_short_code;
                appInfo.app_name = app.app_name;
                appInfo.app_version = app.app_version;
                db.mas_apps.Add(appInfo);
            }
            else
            {
                mas_apps appInfo = new mas_apps();
                appInfo.app_key = app.app_key;
                appInfo.biz_unit_key = app.biz_unit_key;
                appInfo.app_short_code = app.app_short_code;
                db.Entry(appInfo).State = EntityState.Modified;
                db.Entry(appInfo).Property("created_by").IsModified = false;
                db.Entry(appInfo).Property("created_date").IsModified = false;

            }


            if (app.ApplAccessRoleInfo != null)
            {
                foreach (ApplicationAccessRoles pvInfo in app.ApplAccessRoleInfo)///---------------------in this loop its not fetching the newly added row
                {
                            mas_app_access_roles tv = new mas_app_access_roles();

                            //db.mas_app_access_roles.Add(tv);
                            if (pvInfo.app_access_role_key == 0)
                            {
                                tv.app_key = app.app_key;
                                tv.app_access_role_key = pvInfo.app_access_role_key;
                                tv.access_role = pvInfo.access_role;
                                tv.inactive = pvInfo.inactive;
                                tv.created_by = oUser.User.user_key;
                                tv.created_date = DateTime.Now;
                                tv.last_modified_by = oUser.User.user_key;
                                tv.last_modified_date = DateTime.Now;
                                db.mas_app_access_roles.Add(tv);
                                db.SaveChanges();
                            }
                            else
                            {

                                tv.app_key = app.app_key;
                                tv.app_access_role_key = pvInfo.app_access_role_key;
                                tv.access_role = pvInfo.access_role;
                                tv.inactive = pvInfo.inactive;
                                tv.created_by = oUser.User.user_key;
                                tv.created_date = DateTime.Now;
                                tv.last_modified_by = oUser.User.user_key;
                                tv.last_modified_date = DateTime.Now;
                                db.Entry(tv).State = EntityState.Modified;
                                db.SaveChanges();
                                //db.Entry(tv).Property("created_by").IsModified = false;
                                //db.Entry(tv).Property("created_date").IsModified = false;
                            }
                            db.SaveChanges();
                }
            }

Firstly you need to add a hidden input for an Index property in the loop used to generate existing items. This will ensure no consecutive indexers can be bound to the collection when you submit

for (int a = 0; a < Model.ApplAccessRoleInfo.Count; a++)
{
  <tr>
    <td>
      @Html.HiddenFor(m => m.ApplAccessRoleInfo[a].app_access_role_key)
      @Html.EditorFor(m => m.ApplAccessRoleInfo[a].access_role)
    </td>
    <td>
      @Html.CheckBoxFor(ApplTeamAccessInfo[a].inactive) // use CheckBoxFor()
      <input type="hidden" name="ApplTeamAccessInfo.Index" value="@a" /> // add this
    </td>
  </tr>
}

Next you need to inspect the html that you generate for one of the rows and based your template on that. You also need to include the hidden input for the Index property as above. You also need to remove the value attributes (or set them to the default values for the properties) expect for the 2 inputs for the inactive property where the values must be "true) and "false" (currently they are both "false" . It will look like (note: removed data-* attributes for simplicity)

<table id="newrow" style="display:none">
  <tr>
    <td>
      <input name="ApplAccessRoleInfo[#].app_access_role_key" type="hidden" >
      <input name="ApplAccessRoleInfo[#].access_role" type="text" >
    </td>
    <td>
      <input class="check-box" name="ApplTeamAccessInfo[#].inactive" type="checkbox" value="true"> // change value to true
      <input name="ApplTeamAccessInfo[#].inactive" type="hidden" value="false">
      <input type="hidden" name="ApplTeamAccessInfo.Index" value="#" /> // add this
    </td>
  </tr>
</table>

Then the script needs to be

var form = $('form'); // or use the id if you have given the form an id
var newrow= $('#newrow');
var table = $('#RolesDetails');
$(".gridexpand").click(function() {
  var index = (new Date()).getTime(); // unique indexer
  var clone = newrow.clone(); // clone the new row
  clone.html($(clone).html().replace(/#/g, index)); // update the indexer of the clone
  var row = clone.find('tr');
  table.append(row); // add the new row to the table
  // Reparse the validator
  form.data('validator', null);
  $.validator.unobtrusive.parse(form);
});

Note in the script that you need a unique identified for the indexer which is what var index = (new Date()).getTime(); does (currently you set it to "0" but the first row already have an indexer with "0" )

Note also that because you have validation attributes on your properties, you need to reparse the validator when the new row has been added.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM