0

Need some advice on an approach. I have designed a view using a table structure to get the layout I need and populate that table with a foreach loop based on my ViewModel.

I essentially want the user to be able to update some of the fields like noofusers etc and I want to have an addotcart button which will pass those values to the controller.

The problem I have at present is the values do not get passed by the form as they exist outside the form.

If I put in the values in the form I loose any formatting that I get from having a table.

If i repeat the values inside the form but change to hidden for, I get the values from the model passed in not the updated values

I have searched some other posts and have another post on here where it is suggested to not use foreach and use a for loop instead, but that doesn't really change anything in relation to the problem I am experiencing above.

Code is shown below - any suggestions on a general approach to achieve a simple form with a nice layout and still be able to pass values to the controller via a form would be appreciated.

@model PagedList.IPagedList<ShoppingCartCatalogue>
@using Mojito.Domain.ViewModels
@using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Mojito Products</h2>
<div class="col-md-9"></div>
<div class="col-md-3">
    @using (Html.BeginForm("Index", "MojitoProducts", FormMethod.Get))
    {
        <p>
            @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
            <input type="submit" value="Search" />
        </p>
    }
</div>

<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.FirstOrDefault().ImageData)
        </th>
        <th>
            @Html.ActionLink("Category", "Index", new { sortOrder = ViewBag.SortByCategory, currentFilter = ViewBag.CurrentFilter })
        </th>
        <th>
            @Html.ActionLink("Product", "Index", new { sortOrder = ViewBag.SortByProduct, currentFilter = ViewBag.CurrentFilter })
        </th>
        <th>
            @Html.DisplayNameFor(model => model.FirstOrDefault().Description)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.FirstOrDefault().TypeOfSubscription)
        </th>
        <th>
            @Html.ActionLink("Price per user", "Index", new { sortOrder = ViewBag.SortByPrice, currentFilter = ViewBag.CurrentFilter })
        </th>
        <th>
            @Html.DisplayNameFor(model => model.FirstOrDefault().NoOfUsers)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.FirstOrDefault().TotalPrice)
        </th>

    </tr>

    @foreach (ShoppingCartCatalogue t in Model)
    {

        <tr>
            <td>
                @if (t.ImageData != null)
                {
                    <div class="pull-left" style="margin-right: 10px">
                        <img class="img-thumbnail" width="75" height="75"
                             src="@Url.Action("GetImage", "MojitoProducts",
                                                  new { t.MojitoProductId })" />
                    </div>
                }
            </td>
            <td>
                @Html.DisplayFor(modelItem => t.Category, new { Name = "Category", id = "Category" })
            </td>
            <td>
                @Html.DisplayFor(modelItem => t.Name, new { Name = "Name", id = "Name" })
            </td>
            <td>
                @Html.DisplayFor(modelItem => t.Description, new { Name = "Description", id = "Description" })
            </td>
            <td>
                @Html.EnumDropDownListFor(modelItem => t.TypeOfSubscription, new { Name = "TypeOfSubscription", id = "TypeOfSubscription" })
            </td>
            <td>
                @Html.DisplayFor(modelItem => t.Price, new { Name = "Price", id = "Price" })
            </td>
            <td>
                @Html.TextBoxFor(modelItem => t.NoOfUsers, new { Name = "NoOfUsers", id = "NoOfUsers", type = "number", min = "1" })
            </td>
            <td>
                @if (t.TypeOfSubscription.ToString() == "Annual")
                {
                    t.TotalPrice = t.Price * 12;
                }
                else
                {
                    t.TotalPrice = t.Price;
                }
                @Html.DisplayFor(modelItem => t.TotalPrice, new { Name = "Total Price", id = "Total Price" })
            </td>
            <td>

                @using (Html.BeginForm("AddToCart", "ShoppingCart", FormMethod.Post))
                {
                    <div class="pull-right form-group">
                        @if (Request.Url != null)
                        {
                            @Html.HiddenFor(modelItem => t.TypeOfSubscription, new { Name = "TypeOfSubscription", id = "TypeOfSubscription" })
                            @Html.HiddenFor(modelItem => t.NoOfUsers, new { Name = "NoOfUsers", id = "NoOfUsers" })
                            @Html.HiddenFor(modelItem => t.MojitoProductId, new { Name = "MojitoProductId", id = "MojitoProductId" })
                            @Html.HiddenFor(modelItem => t.Category, new { Name = "Category", id = "Category" })
                            @Html.HiddenFor(modelItem => t.Name, new { Name = "Name", id = "Name" })
                            @Html.HiddenFor(modelItem => t.Description, new { Name = "Description", id = "Description" })
                            @Html.HiddenFor(modelItem => t.Price, new { Name = "Price", id = "Price" })
                            if (t.TypeOfSubscription.ToString() == "Annual")
                            {
                                t.TotalPrice = t.Price * 12;
                            }
                            else
                            {
                                t.TotalPrice = t.Price;
                            }
                            @Html.HiddenFor(modelItem => t.TotalPrice, new { Name = "Total Price", id = "Total Price" })
                            @Html.Hidden("returnUrl", Request.Url.PathAndQuery)
                            <input type="submit" class="btn btn-success" value="Add to cart" />
                        }

                    </div>
                }
            </td>
        </tr>

    }

</table>

<div class="col-md-12">
    Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount
</div>
@Html.PagedListPager(Model, page => Url.Action("Index",
        new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
5
  • 1
    Put the table inside of the form? Commented Sep 8, 2014 at 17:24
  • I tried that but all the fields just display next to each other, it appears the format of the table does not apply in the form. Commented Sep 8, 2014 at 17:25
  • 1
    Then this is a css issue, not really a mvc issue. Compare the css being applied to the table outside of the form, with the css being applied to the table inside the form. It's probably just a matter of adding a class to the table and your css file. Commented Sep 8, 2014 at 17:28
  • You were absolutely right - thank you. Commented Sep 8, 2014 at 18:00
  • No problem, I posted this as the answer, feel free to select it. Thanks. Commented Sep 8, 2014 at 18:01

2 Answers 2

2

This is a css issue, not really a mvc issue. Compare the css being applied to the table outside of the form, with the css being applied to the table inside the form. It's probably just a matter of adding a class to the table and your css file.

Sign up to request clarification or add additional context in comments.

Comments

0

3 possible solutions:

  1. Don't use a html tables but instead use css to layout the controls within each form element to give you a tabular layout (for example using floats or absolutely positioned elements
  2. Use jquery to update update the hidden elements with the form whenever the corresponding control outside the form changes (but with this solution your just rendering twice as many controls as necessary and your generating invalid html because of duplicate ID's)
  3. Replace the form and submit elements with a button and use jquery ($.post() method) to post the values to the controller. The advantage of this method is the user stays on the form and can continue to add more elements to the shopping cart. The page would then include a link to the checkout page that shows all items that have been added

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.