简体   繁体   中英

Multiple forms in @foreach loop. How do I submit one asynchronously with javascript. C# core Razor

Shopping cart with many items how to remove any item asynchronously with JavaScript this is my work so far. Can anyone improve on this?

your help would be greatly appreciated. Have a great day

Ok so this works if you remove items from the top of the list but fails if you remove items from some other place.

The problem seems to be that the form names are all the same "remove" without any indexing.

Problem is I'm not sure how to proceed with this.

document.forms['remove'].onsubmit = () => {
        let formData = new FormData(document.forms['remove']);
        fetch('/sales/cart?handler=RemoveItem', {
            method: 'post',
            body: new URLSearchParams(formData)

    })
        .then(() => {
                var url = "/sales/cart?handler=CartPartial";
                console.log(url)
                $.ajax({
                    url: url,
                    success: function (data) {
                        $("#exampleModal .modal-dialog").html(data);
                        $("#exampleModal").modal("show");
                        //alert('Posted using Fetch');
                    }
                });
            });
        return false;
    }

   
    <pre>
       @foreach (var item in Model.Items)
       {
          <form name="remove" method="post">
            <h4 class="text-left text-body">@item.Price.ToString("c")
            <button class="btn btn-sm" title="Trash"><i style="font-size:large" 
             class="text-warning icon-Trash"></i></button>
            </h4>
            <input type="hidden" asp-for="@Model.Id" name="cartId" />
            <input type="hidden" asp-for="@item.Id" name="cartItemId" />
          </form>

       }
   </pre>

Update


----------
New markup
I added an index to the id and included an onclick event.


    <form method="post" id="@i" onclick="removeItem(this.id)">
    <button class="btn btn-sm" title="Trash">Item One</button>
    <input type="hidden" asp-for="@Model.Id" name="cartId" />
    <input type="hidden" asp-for="@item.Id" name="cartItemId" />
    </form>


and create a new function that captured the form id including it in a constant.

    <script>
    function removeItem(formId) {
        const form = document.getElementById(formId);
        form.onsubmit = () => {
            let formData = new FormData(form);
            fetch('/sales/cart?handler=RemoveItem', {
                method: 'post',
                body: new URLSearchParams(formData)
            })
                .then(() => {
                    var url = "/sales/cart?handler=CartPartial";
                    console.log(url)
                    $.ajax({
                        url: url,
                        success: function (data) {
                            $("#exampleModal .modal-dialog").html(data);
                            $("#exampleModal").modal("show");
                            //alert('Posted using Fetch');
                        }
                    });
                });
            return false;
        }
    }
    </script>




If anybody can improve on this please post it here.
Thanks.


Updates code behind Cart.cshtml.cs

    using System;
    using System.Threading.Tasks;
    using Malawby.Models;
    using Malawby.Services.Interfaces;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.RazorPages;

    namespace Malawby.Pages.Sales
    {
    public class CartModel : PageModel
    {
        private readonly ICartRepository _cartRepository;
        public CartModel(ICartRepository cartRepository)
        {
            _cartRepository = cartRepository ?? throw new 
        ArgumentNullException(nameof(cartRepository));
        }

        [BindProperty]
        public Cart Cart { get; set; } = new Cart();

        public const string SessionKeyName = "_Name";
        public string SessionInfo_Name { get; private set; }

        public void OnGetAsync()
        {

        }
        public async Task<PartialViewResult> OnGetCartPartialAsync()
        {
            var userName = GetUserName();
            if (userName != null)
            {
                Cart = await _cartRepository.GetCartByUserName(userName);
            }
            return Partial("_ToCart", model: Cart);
        }
        private string GetUserName()
        {
            return HttpContext.Session.GetString(SessionKeyName);
        }
        public async Task OnPostRemoveItemAsync(int cartId, int cartItemId)
        {
            await _cartRepository.RemoveItem(cartId, cartItemId);                   
        }
        }
        }






I am not familiar with asp.net core, but I will show how I usually do it without focusing on syntax.

first on the view no need to add multiple form but should use card id as index and delete button sent selected index like this:

@foreach (var item in Model.Items)
       {
          <div id="card_@item.cardId">
            <h4 class="text-left text-body">@item.Price.ToString("c")
            <button class="btn btn-sm" onclick="removeItem('@item.cardId') title="Trash"><i style="font-size:large" 
             class="text-warning icon-Trash"></i></button>
            </h4>
          </div>

       }

then the script function will call remove api and remove selected card with no need to re-render the page:

<script type="text/javascript">
    function removeItem(cardId) {
        var removeUrl = "your apiUrl";
        $.post( "removeUrl", { cardId: cardId })
              .done(function( data ) {
                  alert( data ); //usually return true or false if true remove card
                  $('#card_'+ cardId).remove();
         });
    }
</script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM