How to iterate through values of text boxes ,and s

2019-09-16 08:59发布

问题:

I am working on shopping cart using asp.net mvc .I have made complete functionality of shopping cart where user can remove product or update its quantity via text box. But i don't like the part where i have 2 extra links on the right side of each product in cart (update quantity and remove product).I am fine with remove product links cos it makes sense to have remove link for each product. Now i want to have only one button or link called save changes. On click on that button/link i want to gather values from each quantity text box ,pass it to controller and do what its need to be done and return as json object from controller. Problem is that i use ajax for few days only so far and don't know how to iterate/gather values from text boxes in my view and send them to controller.

This is how my shopping cart looks like.

This is my view

@model OnlineShop.ViewModels.ShopingCartViewModel
....
<p class="button">
    @Html.ActionLink("Checkout >>", "AddressAndPayment", "Checkout")
</p>

    <table class="table-bordered">
    <tr>
        headers
    </tr>

    @for (int i = 0; i < Model.CartItems.Count; i++)
    {


        <tr id="row-@Model.CartItems[i].RecordID">
            <td>
                <img src="@Url.Content(Model.CartItems[i].Product.ProductImg)" class="img-responsive" style="width:60px;height:60px;padding:5px;"/>
            </td>
            @*need to be done later*@ 
            <td>

                @Html.ActionLink(Model.CartItems[i].Product.ProductName, "Details", "Store", new{id =Model.CartItems[i].ProductID}, null) 
            </td>
            <td>
                @Model.CartItems[i].Product.ProductPrice
            </td>
            <td>
                @Html.TextBoxFor(model=>model.CartItems[i].CartCount,new { style="width:60px;text-align:center;"})
            </td>
            <td>
                <a href="#" class="UpdateLink" data-id="@Model.CartItems[i].RecordID" txt-id="CartItems_@(i)__CartCount">
                    Update Quantity

                </a>&nbsp;|&nbsp;
            </td>
            <td>
                <a href="#" class="RemoveLink" data-id="@Model.CartItems[i].RecordID">
                    Remove from
                    cart
                </a>
            </td>
        </tr>


    }

    <tr>
        <td>
        </td>
        <td></td>
        <td></td>
        <td></td>
        <td align="center"> <b>Total</b></td>

        <td id="cart-total" align="center">
           <b> @Model.CartTotal</b>
        </td>
    </tr>
</table>
</div>

Scripts

@section scripts {
<script type="text/javascript">
    $(function () {
        // Document.ready -> link up remove event handler
        $(".RemoveLink").click(function () {
            // Get the id from the link
            var recordToDelete = $(this).attr("data-id");
            if (recordToDelete != '') {
                // Perform the ajax post
                $.post("/ShopingCart/RemoveFromCart", { "id": recordToDelete }, function (data) {
                    // Successful requests get here
                    // Update the page elements
                    if (data.ItemCount == 0) {
                        $('#row-' + data.DeleteID).fadeOut('slow');
                    } else {
                        $('#item-count-' + data.DeleteID).text(data.ItemCount);
                    }
                    $('#cart-total').text(data.CartTotal);
                    $('#update-message').text(data.Message);
                    $('#cart-status').text('Cart (' + data.CartCount + ')');
                });
            }
        });
    });
    $(function () {
        // Document.ready -> link up remove event handler
        $(".UpdateLink").click(function () {
            // Get the id from the link
            var recordToUpdate = $(this).attr("data-id");
            var countToUpdate=$("#" + $(this).attr("txt-id")).val();
            if (recordToUpdate != '') {
                // Perform the ajax post
                $.post("/ShopingCart/UpdateCartQuantity", { "id": recordToUpdate, "cartCount": countToUpdate}, function (data) {
                    // Successful requests get here
                    // Update the page elements
                    if (data.ItemCount == 0) {
                        $('#row-' + data.DeleteID).fadeOut('slow');
                    } else {
                        $('#item-count-' + data.DeleteID).text(data.ItemCount);
                    }
                    $('#cart-total').text(data.CartTotal);
                    $('#update-message').text(data.Message);
                    $('#cart-status').text('Cart (' + data.CartCount + ')');
                });
            }
        });
    });
    function handleUpdate() {
        // Load and deserialize the returned JSON data
        var json = context.get_data();
        var data = Sys.Serialization.JavaScriptSerializer.deserialize(json);
        // Update the page elements
        if (data.ItemCount == 0) {
            $('#row-' + data.DeleteID).fadeOut('slow');
        } else {
            $('#item-count-' + data.DeleteID).text(data.ItemCount);
        }
        $('#cart-total').text(data.CartTotal);
        $('#update-message').text(data.Message);
        $('#cart-status').text('Cart (' + data.CartCount + ')');
    }
</script>
}

Thank you for hard work,but that confuses me even more :) ...I'll try to explain better what i am trying to achieve ...this is my controller method

[HttpPost]
        public ActionResult UpdateCartQuantity(int id , int cartCount)
        {
            var cart = ShopingCart.GetCart(this.HttpContext);

            string productName = storeDB.Carts.Single(
                item => item.RecordID == id).Product.ProductName;

            Product product = storeDB.Carts.Single(
                item => item.RecordID == id).Product;

            int oldCount = (int)storeDB.Carts.Single(
                item => item.RecordID == id).CartCount;

            int itemCount = 0;
            if (oldCount==cartCount)
            {
                itemCount = oldCount;
            }
            else if (cartCount>oldCount)
            {
                itemCount = oldCount;
                int sub = cartCount-oldCount;
                for (int i = 0; i < sub; i++)
                {
                    cart.AddToCart(product);
                    itemCount++;
                }
            }
            else
            {

                itemCount = (int)cart.UpdateCartCount(id, cartCount);

            }
            var results = new ShopingCartRemoveViewModel
            {
                Message = Server.HtmlEncode(productName) +
                " has quantity updated.",
                CartTotal = cart.GetTotal(),
                CartCount = (int)cart.GetCount(),
                ItemCount = itemCount,
                DeleteID = id
            };


            return Json(results);
        }

So i was looking at some tutorials and thinking to use <input type="text"> field instead of @html.TextBoxFor(model=>model.CartItems[i].CartCount) and $ajax() to post only recordID and value from each <input> ...I could do that maybe for one cartitem with unique name/id or class but considering that i have list of CartItems i need to dynamically make <input> quantity fields with for statement for each cartitem .So when user press save changes button it needs to read values from each input field and process with method UpdateCartQuantity along with recordID. Main problem for me is how to deal with classes/id's of that <input> dynamically so each has unique id and how to read/send that recordID and input value. Also i edited my view a bit now i have for statement instead of foreach like u can see.

回答1:

  1. jquery textbox's focusout() event with ajax call should do it.
  2. aleksander has a good point too.
  3. u r trying to save individual textbox object state lively. i dont see use for that. except u r trying to trace objects state. after all he has to post his page.


回答2:

  1. give a class to your products list.
  2. validate is number user entered input.
  3. make price readonly.
  4. use focusout() event and jquery to update subtotal and total of this view.

i think this functionality is what u r looking for.

why code more complex than this. in your submit u need id product id and count. everything else is neefed for this page display.



回答3:

Just a guess thats all. there r better ways but this will give u an idea.

public class Product
    {
        //unique
        public int Id
        {
            get;
            set;
        }
        public String Name
        {
            get;
            set;
        }
        public Decimal Price
        {
            get;
            set;
        }
        public Int32 Quantity
        {
            get;
            set;
        }

        public Decimal SubTotal
        {
            get
            {
                return Price * Quantity;
            }
        }

    }

public class ProductList
    {
        public List<Product> productList = new List<Product>
        {
            new Product{Id=1, Name="Product 1", Quantity=4, Price=100},
            new Product{Id=2,Name="Product 2", Quantity=3, Price=200},
            new Product{Id=3,Name="Product 3", Quantity=2, Price=300},
            new Product{Id=4,Name="Product 4", Quantity=1, Price=400}
        };

        public Decimal Total
        {
            get
            {
                Decimal total = 0M;
                foreach( var item in productList )
                {
                    total += item. SubTotal;
                }

                return total;
            }
        }

    }
    <script type="text/javascript">
        function UpdateSubANdTotal(price, quantity, subid) {
            $(subid).html($(quantity).html() * $(price).prop("value"));

            var elems = document.getElementsByClassName('subtotal');
            var tTotal = 0;
            for (var i = 0; i < elems.length; i++) {
                if (typeof elems[i].innerHTML !== null) {
                    tTotal = Number(tTotal) + Number(elems[i].innerHTML);
                }
            }
            $('#ABTotal').text(tTotal);

//as u have updated page, above code. // do an ajax call here to update your db of row with product id and quantity. as product quantity is unique. return an int or boolean for display to user of updated if any. your ajax calling action should accept productid quantity. if needed send some user credentials, if its post not needed.

  1. on focusout page is updated automatically.
  2. an ajax call to update cart db with info.
  3. displaying updated to user.
  4. if user clicks on submit. post action will process cart items and checks out process continue...
  5. if u want ajax call could send entire list ( cart items ) every time user makes change, your choice...

code above and it should be okay.

        }
    </script>

    <div class="">
        @foreach( var item in Model.productList )
        {
            String priceId = "M" + item.Id.ToString();
            String subTotId = "S" + item.Id.ToString();
            String QuanId = "Q" + item. Id. ToString();

            <div class="">
                <label >@item.Name</label>
                <input name="pname[]" id="@priceId" type="text" value="@item.Price" onblur="UpdateSubANdTotal(@priceId, @QuanId, @subTotId)" />
                <label id="@QuanId">@item.Quantity</label>
                <label class="subtotal"  id="@subTotId">@item.SubTotal</label>
            </div>
        }
    </div>

    <label id="ABTotal">@Model.Total</label>

give me post check code, if u can , i will like to take a look. hope this code block is ok.