locked
Deleting nth section deletes following sections as well RRS feed

  • Question

  • User657329123 posted

    Hi there,

    I'm creating a Dynamic section using jQuery. Within this dynamic section, user can create another dynamic sections. If user only addes these nested dynamic sections, all is good.  All the data is correctly posted to controller and saved in the database. But E.g if user adds 3 sections then deletes 2nd section then adds 4th section. Then only 1section is posted to controller.

    Here is the source code that I see in the browser when debugging,

    			<div class="card-body" style="background-color:#d3e2ea;">
    				<div id="NeoMaximumContainer_0">
    					<div class="card" style="margin-bottom: 20px;">
    						<div style="margin-bottom:5px;" class="form-group"></div>
    						<input name="Neomax.Index" class="NeoMax" type="hidden" value="0">
    						<div class="form-group" style="padding:0 15px;">
    							<label>Number or Number Range</label>
    							<input id="NeoDosing_0_NeoMax_0_Amount" name="NeoDosing[0].NeoMax[0].Amount" type="text" value="" class="form-control">
    						</div>
    						<div class="form-group" style="padding:0 15px;">
    							<input type="button" value="Remove" onclick="RemoveNeoMaximumDosing(this);" class="btn btn-sm btn-danger form-control col-sm-2">
    						</div>
    					</div>
    					<div class="card" style="margin-bottom: 20px;">
    						<div style="margin-bottom:5px;" class="form-group"></div>
    						<input name="Neomax.Index" class="NeoMax" type="hidden" value="2">
    						<div class="form-group" style="padding:0 15px;">
    							<label>Number or Number Range</label>
    							<input id="NeoDosing_0_NeoMax_2_Amount" name="NeoDosing[0].NeoMax[2].Amount" type="text" value="" class="form-control">
    						</div>
    						<div class="form-group" style="padding:0 15px;">
    							<input type="button" value="Remove" onclick="RemoveNeoMaximumDosing(this);" class="btn btn-sm btn-danger form-control col-sm-2">
    						</div>
    					</div>
    					<div class="card" style="margin-bottom: 20px;">
    						<div style="margin-bottom:5px;" class="form-group"></div>
    						<input name="Neomax.Index" class="NeoMax" type="hidden" value="3">
    						<div class="form-group" style="padding:0 15px;">
    							<label>Number or Number Range</label>
    							<input id="NeoDosing_0_NeoMax_3_Amount" name="NeoDosing[0].NeoMax[3].Amount" type="text" value="" class="form-control">
    						</div>
    						<div class="form-group" style="padding:0 15px;">
    							<input type="button" value="Remove" onclick="RemoveNeoMaximumDosing(this);" class="btn btn-sm btn-danger form-control col-sm-2">
    						</div>
    					</div>
    				</div>
    			</div>
    

    As you can see sectioon with NeoDosing[0].NeoMax[1].Amount is missing because user removed it. Only 1st section is passed to controller in this case and not the 2nd and 3rd.

    If user doesn't delete any middle section then all data is posted fine which makes me think that naming of the elements is correct but not able to figure out why deleting 2nd section also removes section 3 and 4th.

    Any clues?

    Joe

    Tuesday, November 6, 2018 4:28 PM

All replies

  • User475983607 posted

    Please see the following reference docs which explains how format the HTML to submit non sequential indices.

    https://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

    <form method="post" action="/Home/Create">
    
        <input type="hidden" name="products.Index" value="cold" />
        <input type="text" name="products[cold].Name" value="Beer" />
        <input type="text" name="products[cold].Price" value="7.32" />
        
        <input type="hidden" name="products.Index" value="123" />
        <input type="text" name="products[123].Name" value="Chips" />
        <input type="text" name="products[123].Price" value="2.23" />
        
        <input type="hidden" name="products.Index" value="caliente" />
        <input type="text" name="products[caliente].Name" value="Salsa" />
        <input type="text" name="products[caliente].Price" value="1.23" />
        
        <input type="submit" />
    </form>

    Tuesday, November 6, 2018 5:12 PM
  • User657329123 posted

    How should I model bind a list within a list?

    Here are my models:

        public class NeonatalDosing
        {
            public Guid Id { get; set; }
            [Display(Name = "Dosing Criteria")]
            public string DosingCriteria { get; set; }
            [Display(Name = "Neonatal Maximum")]
            public List<DrugDosingNeoMaximum> NeoMax { get; set; }
            public Guid DrugDosingGuideline_id { get; set; }
            [ForeignKey("DrugDosingGuideline_id")]
            public virtual DrugDosingGuideline DrugDosingGuidelines { get; set; }
        }
    
        public class DrugDosingNeoMaximum
        {
            public Guid Id { get; set; }
            public string Amount { get; set; }
            public Guid NeonatalDosing_id { get; set; }
            [ForeignKey("NeonatalDosing_id")]
            public virtual NeonatalDosing NeonatalDosings { get; set; }
        }
    

    Because of this you see my ids and names as

    id="NeoDosing_0_NeoMax_0_Amount" name="NeoDosing[0].NeoMax[0].Amount

    Where NeoMax is a list within NeoDosing list.

    Tuesday, November 6, 2018 5:46 PM
  • User475983607 posted

    joegreen2005

    How should I model bind a list within a list?

    Here are my models:

        public class NeonatalDosing
        {
            public Guid Id { get; set; }
            [Display(Name = "Dosing Criteria")]
            public string DosingCriteria { get; set; }
            [Display(Name = "Neonatal Maximum")]
            public List<DrugDosingNeoMaximum> NeoMax { get; set; }
            public Guid DrugDosingGuideline_id { get; set; }
            [ForeignKey("DrugDosingGuideline_id")]
            public virtual DrugDosingGuideline DrugDosingGuidelines { get; set; }
        }
    
        public class DrugDosingNeoMaximum
        {
            public Guid Id { get; set; }
            public string Amount { get; set; }
            public Guid NeonatalDosing_id { get; set; }
            [ForeignKey("NeonatalDosing_id")]
            public virtual NeonatalDosing NeonatalDosings { get; set; }
        }

    Because of this you see my ids and names as

    id="NeoDosing_0_NeoMax_0_Amount" name="NeoDosing[0].NeoMax[0].Amount

    Where NeoMax is a list within NeoDosing list.

    As I understand the problem statement, the standard full post model binding does not see the later indices when deleting an middle index.   This is the expected behavior.  The link in my previous post explains how to format the HTML when the indices are not sequential.   Either fix the code so that it follows the correct pattern or populate a JSON object and submit the object using AJAX.

    Perhaps look into a different design where only the selected items are deleted rather than trying to sync the inputs with the DB.

    Tuesday, November 6, 2018 6:18 PM
  • User657329123 posted

    As per the article I'm using .Index and my code works fine when list is part of model. I'm using JavaScript to delete sections. I would like to see if anyone knows of an example. I haven't found any example of model binding list within a list. For time being I will have to change the design.

    Tuesday, November 6, 2018 6:46 PM
  • User1520731567 posted

    Hi joegreen2005,

    As you can see sectioon with NeoDosing[0].NeoMax[1].Amount is missing because user removed it. Only 1st section is passed to controller in this case and not the 2nd and 3rd.

    If user doesn't delete any middle section then all data is posted fine which makes me think that naming of the elements is correct but not able to figure out why deleting 2nd section also removes section 3 and 4th.

    Since you have a dynamic delete action,I think you should add dynamic index in model.( such as:Model[i] )

    And then create some functions with handle index in Js.

    You could refer to this article,this is similar to your question:

    <script language="javascript" type="text/javascript">
            function addRow() {
    
                var index = $("#tbBooks").children("tr").length;
    
                var indexCell = "<td style='display:none'><input name='Books.Index' 
                type='hidden' value='" + index + "' /></td>";
                var titleCell = "<td><input id='Books_" + index + "__Title' 
                name='Books[" + index + "].Title' type='text' value='' /></td>";
                var publishedCell = "<td><input id='Books_" + index + "__Title' 
                name='Books[" + index + "].PublishedDate' type='text' value='' /></td>";
                var removeCell = "<td><input id='btnAddBook' type='button' 
                value='Remove' onclick='removeRow(" + index + ");' /></td>";
    
                var newRow = "<tr id='trBook" + index + "'>" + 
                indexCell + titleCell + publishedCell + removeCell + "</tr>";
                $("#tbBooks").append(newRow);
            }
    
            function removeRow(id) {
                var controlToBeRemoved = "#trBook" + id;
                $(controlToBeRemoved).remove();
            }
        </script>

    Best Regards.

    Yuki Tao

    Wednesday, November 7, 2018 10:00 AM
  • User657329123 posted

    Thanks Yuki. My code is based on same article that mentioned https://www.codeproject.com/Tips/766214/List-Model-Binding-in-MVC. It works great when I have list within a model but not for list within list in a model. 

    I do have index as per the article

    <input name="Neomax.Index" class="NeoMax" type="hidden" value="0">

    Are you saying Index should be part of the model? I'm referring to list within a list like this

    NeoDosing[0].NeoMax[0].Amoun

    Explain me what do you mean by dynamic index? Dynamic isn't a data type.

    Another option I thought is using JavaScript to make ids and names of sections sequential before form is submitted. Will that work?

    Wednesday, November 7, 2018 11:53 AM
  • User1520731567 posted

    Hi joegreen2005,

    Are you saying Index should be part of the model? I'm referring to list within a list like this

    NeoDosing[0].NeoMax[0].Amoun

    Explain me what do you mean by dynamic index? Dynamic isn't a data type.

    Dynamic index means Dynamic variable.In order to adapt to the Index changes brought by the deleting sections.

    According to your code,I think you just use Dynamic variable in the second [ ].

    As I can see in your code:

    NeoDosing[0].NeoMax[0].Amount
    
    NeoDosing[0].NeoMax[2].Amount
    NeoDosing[0].NeoMax[3].Amount

    You could set a variable named 'index' or any other,this variable should related to the count of your sections, like:

    NeoDosing[0].NeoMax[index].Amount

    Another option I thought is using JavaScript to make ids and names of sections sequential before form is submitted. Will that work?

    Sure,it will be work.Any method that can rationalize the index is ok.

    I just provided one method.

    Maybe the method you think of is more suitable for you, the change is smaller.

    Best Regards.

    Yuki Tao

    Thursday, November 8, 2018 2:16 AM