In one of my projects I needed to dynamically display fields to enter information for a collection of objects. Specifically speaking I had a POCO "User" class with FK to a POCO "Child" class. I needed a way to generate text boxes based on how many kids a user had. This involves several steps and here's what I had to do.
1. Create a partial view with the fields you need to capture the info for a "Child"
3. Create the javascript that will call the action above from another control. ex: onclick event of a link that should add the control for adding a "Child"
1. Create a partial view with the fields you need to capture the info for a "Child"
@{
    var seed = ViewBag.Seed;
      
    
        @{
            @*MVC renders fields for a collection by appending an index, which I am setting up below*@
              var ageIdText = "Children_" + seed + "__Age";
              var ageNameText = "Children[" + seed + "].Age";
              var genderIdText = "Children_" + seed + "__Gender";
              var genderNameText = "Children[" + seed + "].Gender";
              var deleteIdText = "Children_" + seed + "__Delete";
              var deleteNameText = "Children[" + seed + "].Delete";
            }
            
          
        
        
        
        
        Remove
    
    
    
                 
        
    }
MVC renders controls for collections by attaching an index for the collection. I had to code this in to render based on the number of controls that need to be displayed. Ex: the age text field will be Children_[1]__Age and so forth. I will explain the reason for having a delete field a little later.
2. Create an action in the controller that will return the partial view
public ActionResult RenderChildren(int? id, int? seed, string viewType)
        {
            //if no of children to be rendered in the view was not send in the request url, then render only one child
            if (id.HasValue)
                ViewBag.Children = id;
            else
                ViewBag.Children = 1;
            //if the collection index was not indicated, then start rendering the controls from 0. 
            //This will come in handy when there are already controls on the page and we want to add more.
            if (seed.HasValue)
                ViewBag.Seed = seed;
            else
                ViewBag.Seed = 0;
            return PartialView(viewType);
        }
It is important to keep track on the index for the collection, or you will get unexpected results.
3. Create the javascript that will call the action above from another control. ex: onclick event of a link that should add the control for adding a "Child"
function addChild(method,container,type) {
    var noofChild = $(container).find('.mark-for-delete').length;
    $.get('/account/'+method+'?seed=' + (noofChild)+"&viewtype="+type, function (template) { $(container).append(template); });
}
4. Call the javascript
Add a child
function deleteChildren(element, deleteElement) {
    $container = $(element).parent();
    $container.find(deleteElement).val('True');
    $container.hide();
}
This will take care of dynamically rendering the required number of fields for "Child"
5. Handling the deletes - I also needed to provide the user to delete existing fields
RemoveTo handle the delete I need some more javascript code that will add some value to the hidden field that I added to my partial view. This value can then be picked up via the model while updating the database. I do have a property in the "Child" POCO class for setting the delete value. This field is not mapped to the database.
 
No comments:
Post a Comment