1

I am trying to add a remove/delete a dynamically created partial view. This is my ADD script.

    $("#btnAdd").on('click', function () {
    $.ajax({
        async: false,
        url: '/Employees/Add'
    }).success(function (partialView) {
        $('#AddSchedule').append("<tbody>" + partialView + "</tbody>");      
    });
});

this is the add controller

public ActionResult Add()
    {
        var schedViewModel = new FacultySchedViewModel();
        return PartialView("~/Views/Employees/_DynamicView.cshtml", schedViewModel);
    }

this is the partial view _DynamicView.cshtml

@using(Html.BeginCollectionItem("New")){
    <td>
        @Html.ActionLink("Delete", "DeleteThis", "MyController", null)
    </td>
    <td>
        @Html.EditorFor(model => @Model.Schedule, new { htmlAttributes = new { @class = "form-control" } })
    </td> }

what i can't figure out are

  1. how to get the ID generated by BeginItemCollection
  2. use the ID in a remove script
  3. action on the controller

EDIT 1. How to connect it to a button or a link for removing the row

Added the view on the the Main of the partial view

 @for (int i = 0; i < @Model.New.Count(); i++)
                {               
                   @Html.EditorFor(model => @Model.New[i])

                }
makoto
  • 177
  • 1
  • 4
  • 16
  • What do your mean _"the ID generated by BeginItemCollection"_. The `BeginItemCollection` add a `Guid` as an indexer to the controls `name` and `id` attributes. It has no relevance at all to identifying an item to delete. Show you `remove` function (but why do you also have an action link to a delete method?) –  Mar 21 '15 at 07:07
  • Do you mean you want to remove the html appended to `#AddSchedule` previously added by a corresponding add, in javascript? – StuartLC Mar 21 '15 at 07:08
  • And what is the property in `FacultySchedViewModel` that uniquely identifies it (which is what you need to delete the item) –  Mar 21 '15 at 07:10
  • @StephenMuecke. I added an edit in my question. And for your second question - its ID but i didn't include it my view model.. so I will include it.. – makoto Mar 21 '15 at 07:14
  • @StuartLC.. yes, exactly.. on some post that I've read it the remove script has some `('#AddSchedule').empty();` but it seems like it will remove all apended partial view.. I'm not sure though.. – makoto Mar 21 '15 at 07:17
  • what is "AddSchedule"? is it table or div? and for remove, are you want at client side or at server side operation you want. – Ajay2707 Mar 21 '15 at 07:46
  • @arjay the `AddSchedule` is a table.. and I need a client side removal – makoto Mar 21 '15 at 08:00

2 Answers2

2

The BeginItemCollection add a Guid as an indexer to the controls name and id attributes. It has no relevance at all to identifying an item to delete. You need add include the value of the property that identifies the FacultySchedViewModel object. Assuming its int ID, then change the partial to include a button and add the ID as a data- attribute

@using(Html.BeginCollectionItem("New"))
{
  <tr>
    <td><button type="button" class="delete" data-id="@Model.ID">Delete</button></td>
    <td>@Html.EditorFor(model => @Model.Schedule, new { htmlAttributes = new { @class = "form-control" } })</td>
  </tr>
}

Then your script would be

var url = '@Url.Action("Delete")'; // assumes its in the same controller
$('.delete').click(function() {
  var id = $(this).data('id');
  var row = $(this).closest('tr');
  if (id) { // or if(id == 0) depending if your property is nullable
    row.remove(); // the item never existed so no need to call the server
    return;
  }
  $.post(url, { ID: id }, function(response) {
    if(response) {
      row.remove(); // OK, so remove the row
    } else {
      // Oops - display and error message?
    }
  });
});

and the controller

[HttpPost]
public JsonResult Delete(int ID)
{
  // Delete the item in the database
  return Json(true); // or if there is an error, return Json(null); to indicate failure
}

Side note:

  1. $('#AddSchedule').append("<tbody>" + partialView + "</tbody>"); is adding a new tbody element for each item. Instead the main view should include the tbody element and give it the id so its $('#AddSchedule').append(partialView); or use $('#AddSchedule tbody')append(partialView);
  2. Does the model your posting back really have a property named New (as you indicate in the BeginItemCollection method)?
  • Sorry I didn't save it in the database.. how will I remove it in the controller? – makoto Mar 21 '15 at 07:37
  • See my updates. If the model has not yet been saved, you just check the ID (i.e. `null` if its `int? ID` or `0` if its `int`) and if so just remove the row from the table - no need to call controller –  Mar 21 '15 at 07:39
  • I added the on the append for the style... And the property of `BeginItemCollection` method is really `New`.. – makoto Mar 21 '15 at 07:59
  • Why have a property named `New`? This means if you want to edit existing items you need to create a separate partial with identical code (just changing the generated prefix). Surely the fact the ID is either `null` or `0` identifies it as a new vs existing `FacultySchedViewModel` –  Mar 21 '15 at 08:03
  • You should not be adding a `` element for each row. Just style the `` element (note I added that in my code in the partial - the valid child of a `` element is a `` element, not `` elements) –  Mar 21 '15 at 08:05
  • the New is a list in the model that is used in the loop on the main view... I added the code of the loop – makoto Mar 21 '15 at 08:37
  • Sorry, but that makes no sense. You have a `$("#btnAdd")` function that adds a new record. How can `Model.New` have any items (they don't exist yet!) What about existing items that do exist - would you have a property named `Existing`. –  Mar 21 '15 at 08:45
0

As per your html render, what I suggest to modify your partial view as

From 
  @Html.ActionLink("Delete", "DeleteThis", "MyController", null)
To
  @Html.ActionLink("Delete", "DeleteThis", "MyController", new { hidefocus = "hidefocus" } )  //add custom properties for here, which you can grab at client side or give css here.

Now search the anchor link via jQuery: Find the element with a particular custom attribute When you get id, you can go parent like $('#id').parent().parent().hide() or empty()

or

As second option, is on click of Delete button call the same controller , but with a parameter to identify delete, so while returning give the null will bind in ajax again with empty string.

Why does Html.ActionLink render "?Length=4"

http://forums.asp.net/t/1787278.aspx?Add+and+remove+partial+views

Community
  • 1
  • 1
Ajay2707
  • 5,690
  • 6
  • 40
  • 58