0

I am getting quite responses when I add/delete rows.

When page is loaded the default rows 3 will be added.(But user can delete those rows) When I am trying to add new row then 4 value rows are coming in controller but when I am trying to delete any default row then it is not showing the newly added row. Here is my below code.

@model ProductRegistration.Models.InstalledProductInformationModel
@using (Html.BeginForm())
{
    @for (int i = 0; i < ((Model != null && Model.listInstallProducts != null) ? Model.listInstallProducts.Count : 3); i++)
    {
        <tr>
            <td>
                @Html.TextBoxFor(m => m.listInstallProducts[i].SerialNumber, new { @class = "form-control input-sm input-Serial", @placeholder = "Enter serial number", @maxlength = 50, @OnKeypress = "return alphanumeric_only(event);" })
                @Html.ValidationMessageFor(m => m.listInstallProducts[i].SerialNumber)
                <div class="SerialErrorDisplay" style="color: red"></div>
            </td>
            <td>
                @Html.DropDownListFor(m => m.listInstallProducts[i].ModelNumber, new SelectList(string.Empty, "Value", "Text"), "--Select Model--", new { @class = "form-control input-sm input-Model" })
                @Html.ValidationMessageFor(m => m.listInstallProducts[i].ModelNumber)
                <div class="ModelErrorDisplay" style="color: red"></div>
            </td>
            <td>
                @Html.TextBoxFor(m => m.listInstallProducts[i].InstallationDate, new { @class = "form-control input-sm input-Date", @maxlength = 50, @placeholder = "DD/MM/YYYY" })
                @Html.ValidationMessageFor(m => m.listInstallProducts[i].InstallationDate)
                <div class="DateErrorDisplay" style="color: red"></div>
            </td>
            <td>
                <img src="~/Images/delete_icon.png" onclick="DeleteProduct(this);" />
            </td>
        </tr>
    }
    <input class="btn btn-primary top-padding" type="submit" value="Previous" id="back-step" name="direction"/>
}

In Controller:

public ActionResult InstalledProductInfo(InstalledProductInformationModel InstalledProducts, string direction)
{
    if(ModelState.IsValid)
    {
        return RedirectToAction("EquipmentOwnerInfo");
    }
    return View(InstalledProducts);
}

Model is:

public class InstalledProductInformationModel : InstalledProductInformation
{
    public InstalledProductInformation installedProductInformation { get; set; }
    public List<InstalledProductInformation> listInstallProducts { get; set; }
}

please help me out.

tereško
  • 58,060
  • 25
  • 98
  • 150
Satya
  • 185
  • 1
  • 2
  • 16

2 Answers2

0

List indexes are enumerated continuously, so there can be no gap. If You remove one row, the list index is no more continuous. The new row should be there if You will deal with indexes.

  • Means...?? can you please little bit more or can you send me any reference link?? – Satya Mar 24 '15 at 07:46
  • Look at Your form code. Following Razor code that You gave, Your form inputs should contain indexes. 1st text box will be listInstallProducts[0], 2nd box will be listInstallProducts[1] and so on. When You add new row and remove one of default rows, let's say 3rd, you have indexes 0,1 and 3 in Your form, index 2 is missing. But wait, list cannot have gaps in indexes in C#. That's why your model binder binds only rows 0 and 1 to the list and leaves row 4. – Algirdas Brazas Mar 24 '15 at 10:07
  • Stephen Muecke already gave the answer - hidden property `Index`. You can find more at http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/ – Algirdas Brazas Mar 24 '15 at 13:33
0

By default, the DefaultModelBinder required collection indexers to start at zero and be consecutive. If you delete the first item (indexer = 0) then no items will be bound. If you delete the 3rd item (indexer = 2) then only the first 2 items will be bound. You can override this behavior by adding an input for a special property named Index where the value equals the indexer.

@for (int i = 0; i < ((Model != null && Model.listInstallProducts != null) ? Model.listInstallProducts.Count : 3); i++)
{
  <tr>
    <td>
      @Html.TextBoxFor(m => m.listInstallProducts[i].SerialNumber, new { @class = "form-control input-sm input-Serial", @placeholder = "Enter serial number", @maxlength = 50, @OnKeypress = "return alphanumeric_only(event);" })
      @Html.ValidationMessageFor(m => m.listInstallProducts[i].SerialNumber)
      <div class="SerialErrorDisplay" style="color: red"></div>
    </td>
    ....
    <td>
      // Add the following input
      <input type="hidden" name="listInstallProducts.Index" value="@i" /> 
      <img src="~/Images/delete_icon.png" onclick="DeleteProduct(this);" />
    </td>
  </tr>
}
<input class="btn btn-primary top-padding" type="submit" value="Previous" id="back-step" name="direction"/>

Side note: You should be adding the 3 items in the controller before you pass the model to the view so you get proper model binding and then simply use @for (int i = 0; i < Model.listInstallProducts.Count; i++)

  • But I got another problem. Here i am validating required field attributes. So when i entered new row and clicks submit button the validation is not displayed . But it can be validated (showing required)again if we hit submit. how can you achieve this? – Satya Mar 24 '15 at 07:54
  • That's a different question so you need to ask a new question (but you need to reparse the validator when adding dynamic content). Refer [this answer](http://stackoverflow.com/questions/26542509/validate-dynamically-added-fields/26542591#26542591) for an example –  Mar 24 '15 at 07:58
  • Can you please explain little bit more.. please – Satya Mar 24 '15 at 08:04
  • Explain which bit, my answer or reparsing the validator (note I added link)? –  Mar 24 '15 at 08:05
  • Here we are not using "unobtrusive.js". We are validating using server validations only – Satya Mar 24 '15 at 08:17
  • Then you need to ask a new question with the details of the validation code. –  Mar 24 '15 at 08:19
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/73648/discussion-between-user3017179-and-stephen-muecke). – Satya Mar 24 '15 at 08:48