0

I want to get in controller and Model and specific value from collection which equal line on which I press button

 <table id="Products" class="Products">
    <tr>
        <th>ProductId</th>
        <th>Productname</th>
        <th>Quantity</th>
        <th>UnitPrice</th>
    </tr>
    <% for(int i=0; i < Model.NorthOrderDetails.Count; i++)
       {                            %>
              <tr>
        <td><%: Html.Label(Model.NorthOrderDetails[i].ProductID.ToString()) %></td>
        <td><%: Html.Label(Model.NorthOrderDetails[i].ProductName) %> </td>
        <td><%: Html.TextBoxFor(m => m.NorthOrderDetails[i].Quantity) %></td>
        <td><%: Html.TextBoxFor(m => m.NorthOrderDetails[i].UnitPrice) %></td>
        <td><%:  @Html.ActionLink("Go to second view", "ViewTwo", "Order", Model, null)%></td>
         <input type="submit" title="ads" value =<%: Model.NorthOrderDetails[i].ProductID.ToString()%> name=ssad /> 
 <tr>
                 <% } %>

</table>

Can I set value in submit from collection, for example

     <input type="submit" title="ads" value =<%: Model.NorthOrderDetails[i].ProductID.ToString()%> name=ssad /> 

And this value will equal 17, for example in controller. This work, but how I can change of text in button from value in collection to any text?

UPDATE I use code of Stephen Muecke, but I edit table because I use aspx page

 <td><button type="button" class="delete" data-id="<%:Model.NorthOrderDetails[i].ProductID %>">Delete</button><td> 
    <td><input type="hidden" name="<%:Model.NorthOrderDetails[i].ProductName %>" value="<%:i %>" /><td>

And, unfortunately the script doesn't call controller

user4523894
  • 143
  • 1
  • 1
  • 10
  • This will not work. Your submit button will post back the form which contains the whole collection. If your wanting to post back just one object in the collection then you need a different approach (ajax would be best) - but why not post back the whole collection anyway? –  Mar 04 '15 at 08:09
  • @StephenMuecke. I want to sent all Model and one specific value of collection in model, because I want to get fresh/new values in table for updating them in session and I want to delete one item from collection in which I press button – user4523894 Mar 04 '15 at 08:12
  • 1
    The value of a submit button is posted back, so you can check `FormCollection` or add an additional parameter to the POST method - eg `public ActionResult Views(IEnumerable model, int sad)` –  Mar 04 '15 at 08:16
  • @StephenMuecke Can u edit my question. Not clear understand – user4523894 Mar 04 '15 at 08:24
  • @StephenMuecke. This work name=ssad /> But know I have buttons with names 2,17 from collection – user4523894 Mar 04 '15 at 08:28
  • That's the only way to make it work with you current design, but you really need to rethink what your doing. Why post back everything when clicking the button is only intended to delete the associated item. You should be using ajax. –  Mar 04 '15 at 08:35
  • @StephenMuecke. Ok. can u advise me some links about ajax for solving this problem? – user4523894 Mar 04 '15 at 08:54
  • Am I correct in assuming that you want to be able to edit all items at once, and to be also able to delete individual items? - If so I can post an answer a bit later. –  Mar 04 '15 at 08:56
  • @StephenMuecke. Ok. and I will learn ajax. Finally, I have understood that it need me. Your answer I accept, of course – user4523894 Mar 04 '15 at 09:02
  • @StephenMuecke. All right – user4523894 Mar 04 '15 at 09:08

1 Answers1

2

Rather than doing a full post and regenerating the view each time you want to delete an item, you can use ajax to post the items ID value to a controller method that deletes the item in the database and then remove that item from the DOM. This will greatly improve performance and means you can probably avoid using Session.

Change the view to (sorry, but this is Razor syntax)

  @for (int i = 0; i < Model.NorthOrderDetails.Count; i++)
  {
    <tr>
      <td>@Html.LabelFor(Model.NorthOrderDetails[i].ProductID)</td> // ToString not required
      <td>@Html.Label(Model.NorthOrderDetails[i].ProductName)</td>
      <td>@Html.TextBoxFor(m => m.NorthOrderDetails[i].Quantity)></td>
      <td>@Html.TextBoxFor(m => m.NorthOrderDetails[i].UnitPrice)</td>
      <td>@Html.ActionLink("Go to second view", "ViewTwo", "Order", Model, null)</td> // This wont work
      <td>
        <button type="button" class="delete" data-id="@Model.NorthOrderDetails[i].ProductID">Delete</button><td> // change this
        <input type="hidden" name="@Model.NorthOrderDetails.Index" value="@i" /> // add this
    </tr>
  }
  </table>
  <input type="submit" value="Save" /> // add this

Notes:

  1. Your action link will not work (your cannot pass a collection to a GET method) I suspect you mean @Html.ActionLink("Go to second view", "ViewTwo", "Order", new { ID = Model.NorthOrderDetails[i].ProductID }, null) so you can pass the productID to the ViewTwo() method
  2. Change the submit button in each row to a normal button, and add one submit button at the end (to save all changes to your textboxes in one post)
  3. Add the special hidden input for an Index property. This is used by the DefaultModelBinder to match up collections where the indexers are non-consecutive (which they will be if you delete items in the middle of the collection)
  4. You don't render any input for the ProductID which means you wont be able to identify the products on post back. You will need to add a hidden input for it

Then add the following script

var url = '@Url.Action("Delete", "YourControllerName")';
$('.delete').click(function() {
  var id = $(this).data('id'); // Get the product ID
  var row = $(this).closest('tr') // Get the table row
  $.post(url, { ID: id }, function(data) {
    if(data) {
      row.remove(); // remove the row from the table
    } else {
      // oops!
    }
  });
});

And the controller

public ActionResult View(IEnumerable<YourModel> model)
{
  // Save your collection and redirect
}

[HttpPost]
public JsonResult Delete(int ID)
{
  // Delete the product in the database based on the ID
  return Json(true);
}

Note: If deleting an item could throw and exception of fail in some way, then you should return Json(null); so it can be checked in the ajax method.

  • Not sure what your mean, how can the script 'work' if it does not call the controller? Are you getting any error in the browser console? –  Mar 04 '15 at 18:12
  • No. In browser console I don't get errors, but controller doesn't call – user4523894 Mar 04 '15 at 18:13
  • Sorry, Its `$('.delete').click(function() {` (left off the dot to indicate a class name) –  Mar 04 '15 at 18:14
  • Put a beak point on the script and step through it, and add some `console.log()` statements to check the variables are correct –  Mar 04 '15 at 18:30
  • Also have you put the script in a document.ready() function or placed it at the bottom of the page? –  Mar 04 '15 at 18:31
  • Yes. I place in the end of the file and in variable id I see correct numbers, in row I get Object – user4523894 Mar 04 '15 at 18:34
  • `row` will be the table row DOM element so that's OK. Is the url correct? Also put `[HttpPost]` on the method (although it should not be the issue). I can't see anything obvious - it works for me. Is there anything that you have changed or added to the code I have shown? –  Mar 04 '15 at 18:40
  • I edit question. I edit for code for correct aspx page – user4523894 Mar 04 '15 at 18:52
  • @user4523894, You need to roll back that edit - the question and my related answer now makes no sense. You need to leave the original question and add any edits after it. –  Mar 04 '15 at 18:55
  • I cant see why it wont work. You haven't put a `[ValidateAntiForgeryToken]` attribute on the `Delete()` method have you? –  Mar 04 '15 at 19:19
  • Is `ProductID` typeof `int`? - if not you would need to change the signature of the `Delete()` method. –  Mar 04 '15 at 19:28
  • var url = '<%:Url.Action("Delete", "Order")%>'; It works. great thanks. But row in table doestn disappear. But I will try to do it myself – user4523894 Mar 04 '15 at 19:29
  • If I want to add row in table and then add record in DB I need use ajax for adding better than server code? – user4523894 Mar 05 '15 at 07:53
  • You will get better performance because it saves you from having to post, redirect and render the full view again. But it does add extra complexity. [This answer](http://stackoverflow.com/questions/28849296/set-value-submit-from-collection-submit-mvc/28851660?noredirect=1#comment46008019_28851660) gives some options you can consider. –  Mar 05 '15 at 08:41
  • Oops, I meant [this one](http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) –  Mar 05 '15 at 20:59
  • Thanks. Can you look on this question. Script doesn't work correctly http://stackoverflow.com/questions/28886230/jquery-script-delete-all-items-in-forms-collection – user4523894 Mar 06 '15 at 06:40