Question

I have a strongly typed view with Model that represents multiple objects in List. On this view I generate Grid and each object represent one row in a grid. Then I pass specific object from this model List to partial view. This partial view is actually a popup window. On popup window I have a form where user can correct one row (one object) and submits back to Action, where I save changes to database. How can I pass specific object from view to partial view, when i click on specific "row"?

Is it possible to save for example ID of specific row to hidden field and then dynamically read this value from hidden field when rendering the partialview or when passing Model to partial view? Or is the whole concept wrong?

View Code

@model IEnumerable<Loyalty.Models.GridColumns>
@using GridMvc.Html
@using GridMvc.Sorting

<input type="button" id="opener" title="open popup" value="test1"/>
<a onclick="EditUser(1)">edit</a>

@Html.Grid(Model).AutoGenerateColumns()

<div id="EditUser" title="Popravi uporbnika">
    @{
        //Here I would like to get value from hidden field and change it with value 1
        //in a WHERE sentance in the line below
        Html.RenderPartial("EditUser", Model.Where(m => m.ID == 1).Single());
    }
</div>

<script  type="text/javascript">
    $("#opener").click(function () {
        $("#EditUser").dialog("open");
    });
    $(function() {
        $("#EditUser").dialog({
            open: function() {
                $("body").addClass("blur");
            },
            clse: function () {
                $("body").removeClass("blur");
            },
            modal: true,
            closeText:  "Close",
            autoOpen: false,
            width: 800,
            height: 600
        });
    });

    }
</script>

PartialView Code

@model Loyalty.Models.GridColumns

@using (Ajax.BeginForm("UpdateUser", "Home", new AjaxOptions () { UpdateTargetId="ID", OnSuccess="onSuccess()"}))
    {
        <fieldset class="PopUp">
            <legend class="PopUp">General data</legend>
            <div class="EditLabel">
                Name:
            </div>
            <div class="EditValue">
                @Html.TextBoxFor(m => m.FirstName)
            </div>

            <div class="EditLabel">
                Last name:
            </div>
            <div class="EditValue">
                @Html.TextBoxFor(m => m.LastName)
            </div>

             <div class="EditLabel">
                Birth date: 
            </div>
            <div class="EditValue">
                @Html.TextBoxFor(m => m.BirthDate, "{0:dd-MMM-yyyy}")
            </div>

            <div class="EditLabel">
                Gender: 
            </div>
            <div class="EditValue">
                @{
                    var item1 = new SelectListItem();
                    item1.Text = "male";
                    var item2 = new SelectListItem();
                    item2.Text = "female";
                    List<SelectListItem> items = new List<SelectListItem>();
                    items.Add(item1);
                    items.Add(item2);
                    var SelectItems = new SelectList(items, "Value", "Text");
                }

                @Html.DropDownListFor(m => m.Gender, SelectItems)
            </div>
        </fieldset>

        <fieldset class="PopUp">
            <legend class="PopUp">Address</legend>
            <div class="EditLabel">
                Street:
            </div>
            <div class="EditValue">
                @Html.TextBoxFor(m => m.Street)
            </div>

            <div class="EditLabel">
                House no.:
            </div>
            <div class="EditValue">
                @Html.TextBoxFor(m => m.HouseNumber)
            </div>

            <div class="EditLabel">
                Town:
            </div>
            <div class="EditValue">
                @Html.TextBoxFor(m => m.Town)
            </div>

            <div class="EditLabel">
                Post code:
            </div>
            <div class="EditValue">
                @Html.TextBoxFor(m => m.PostNumber)
            </div>
        </fieldset>

        <fieldset class="PopUp">
            <legend class="PopUp">Contact info</legend>
            <div class="EditLabel">
                Phone: 
            </div>
            <div class="EditValue">
                @Html.TextBoxFor(m => m.PhoneNumber)
            </div>

            <div class="EditLabel">
                E-mail: 
            </div>
            <div class="EditValue">
                @Html.TextBoxFor(m => m.Email)
            </div>
        </fieldset>
    }

Main View Action

    public ActionResult Index()
            {    
                var UsersCollection = new List<GridColumns>();
                for (int i = 1; i <= 31; i++)
                {
                    bool disc = false;
                    if (i % 2 == 0)
                    {
                        disc = true;
                    }
                    else
                    {
                        disc = false;
                    }

                    UsersCollection.Add(new GridColumns() {ID = i, BirthDate = new DateTime(2014,1,i), Email = "user" + i + "@email.com", FirstName = "User1" + i, LastName = "User1LastName" + i, Gender = "male", Discount = disc, Cupons = i });
                }

                return View(UsersCollection);
            }

PartialView Action

    [HttpPost]
    public ActionResult UpdateUser(GridColumns person)
    {
        return PartialView();
    }

Partial View action is called when submitting popup form.

Model

[GridTable(PagingEnabled=true, PageSize=20)]
    public class GridColumns
    {
        [GridColumn(Title="ID", SortEnabled=true)]
        public int ID { get; set; }

        [GridColumn(Title="First name", FilterEnabled=true, SortEnabled=true)]
        public string FirstName { get; set; }

        [GridColumn(Title = "Last name", FilterEnabled = true, SortEnabled = true)]
        public string LastName { get; set; }

        [GridColumn(Title = "Birth date", FilterEnabled = true, Width = "150", Format = "{0:dd-MMM-yyyy}")]
        public DateTime BirthDate { get; set; }

        [GridColumn(Title = "gender", FilterEnabled = true)]
        public string Gender { get; set; }

        [GridColumn(Title = "e-mail", FilterEnabled = true, SortEnabled = true)]
        public string Email { get; set; }

        [GridColumn(Title = "Phone", FilterEnabled = true, SortEnabled = true)]
        public string PhoneNumber { get; set; }

        [GridColumn(Title = "Street", FilterEnabled = true)]
        public string Street { get; set; }

        [GridColumn(Title = "House no.", FilterEnabled = true)]
        public string HouseNumber { get; set; }

        [GridColumn(Title = "Town", FilterEnabled = true)]
        public string Town { get; set; }

        [GridColumn(Title = "Post number", FilterEnabled = true)]
        public int PostNumber { get; set; }            
    }
Was it helpful?

Solution

I don't mean to be harsh, but if you're going to develop for the web, then you need to learn how the web works. In HTTP, you have a server and a client. The client sends a request to the server for some resource and that serve sends back a response. This is referred to as the request-response cycle. The "cycle" part is key because the connection is not maintained indefinitely. After the server sends the response, the connection is closed, and if the client needs something further, it issues a new request.

So, now let's consider what you're trying to accomplish. You have a partial view that is rendered server-side and you want to render something different based on something that's going to happen client-side (a click). That's not possible. By the time the user can click something, the server has already done it's job and moved on.

Now, it was just because of this limitation that AJAX was developed. AJAX is simply a way to make HTTP requests on page without have to force a browser reload. Think of it as a mini stripped-down browser inside your web page. If you want some HTML to be rendered based on a user click, then you must use JavaScript to catch and handle that click event, send an HTTP request to the server for that bit of HTML, and then render the returned data to the page once you receive the response. Simplistically, this can be achieved with the following:

JavaScript

$('.row').on('click', function () {
    $.get('/url/to/action/that/returns/html', { id = [something] }, function (result) {
        $('#Something').html(result);
    }
});

Controller Action

public ActionResult GetRowHtml(int id)
{
   // whatever
   return View("_RowHtml");
}

Partial View

@{ Layout = null; }
<!-- your html -->

The pieces you'll have to fill in because I can't make those assumptions for you are:

  1. How you will get the row id in your JS. You could add it as a data attribute on your table row and then retrieve it with $(this).data('id'). You could simply pull it from a known data cell with $(this).find('td.myIdCell').text(). You can't really set it as the actual id attribute of the row because HTML ids must start with an alpha character, but you could potentially do something like id="row1", where 1 is the id and use JS string manipulation functions or a regex pattern to pull it out.

  2. What the id will actually be used for in your action. This is just your straight-up business logic.

  3. What happens with the returned HTML. I simply set the HTML content of some element with id, #Something. Your logic is probably going to be more complicated, perhaps requiring selecting the table or something first than then appending items to the DOM.

OTHER TIPS

I would bind a javascript function to the row click event of your grid, and assuming the key of the grid is the ID you are after:

function showPopup(id){
     var url = 'someActionThatPopulatesPartialView/' + id;
     $.get(url, function(data){
          $('#EditUser').html(data);
     });
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top