views:

173

answers:

1

On a list page, clicking on one of the items brings up the details in a modal popup window which will have its own functionality (like validation, updating etc). What's the best practice to implement this (not looking for a hack). I see two options here:

  1. Hide the details markup until a list item is clicked at which time, do a ajax request to get the details and populate and show the details section.

  2. Have the details section as a separate page by itself. On a list item click, show this page in a modal window (is this even possible?) This is similar to the IFrame approach and sounds like an old school approach.

What are the pros of cons of these approaches or are there other ways of doing this? There should not be a postback on list item click.

Edit: Any more opinions are appreciated.

+1  A: 

I'm doing option 1 currently, it's very lightweight and all you need is an ajax post (jQuery or UpdatePanel) and some modal (I'm using jQery UI). It's easier than a full page post, plus you have the added benefit of being able to manipulate the page you're in as part of the result.

For example I have grids in the page, the editor is modal, usually with more detail, when you hit save, the grid is updated. I've put this in a generic template solution and it's very easy to work with, and is as light as webforms can be in that situation, so I'm all in favor of option 1.

Here's an example approach, having your modal control inherit from UpdatePanel (code condensed for brevity):

public class Modal : UpdatePanel
{
  private bool? _show;
  public string Title
  {
    get { return ViewState.Get("Title", string.Empty); }
    set { ViewState.Set("Title", value); }
  }

  public string SaveButtonText
  {
    get { return ViewState.Get("SaveButtonText", "Save"); }
    set { ViewState.Set("SaveButtonText", value); }
  }

  protected override void OnPreRender(EventArgs e)
  {
    if (_show.HasValue) RegScript(_show.Value);
    base.OnPreRender(e);
  }

  public new Modal Update() { base.Update();return this;}      
  public Modal Show() { _show = true; return this; }
  public Modal Hide() { _show = false; return this; }

  private void RegScript(bool show)
  {
    const string scriptShow = "$(function() {{ modal('{0}','{1}','{2}'); }});";
    ScriptManager.RegisterStartupScript(this, typeof (Modal), 
           ClientID + (show ? "s" : "h"), 
           string.Format(scriptShow, ClientID, Title, SaveButtonText), true);
  }
}

In javascript:

function modal(id, mTitle, saveText) {
  var btns = {};
        btns[saveText || "Save"] = function() {
            $(this).find("input[id$=MySaveButton]").click();
        };
        btns.Close = function() {
            $(this).dialog("close");
        };
        return $("#" + id).dialog('destroy').dialog({
            title: mTitle,
            modal: true,
            width: (width || '650') + 'px',
            resizable: false,
            buttons: btns
        }).parent().appendTo($("form:first"));
    }

Then in your markup (Can't think of a better name than MyControls right now, sorry!):

<MyControls:Modal ID="MyPanel" runat="server" UpdateMode="Conditional" Title="Details">
  //Any Controls here, ListView, whatever
   <asp:Button ID="MySaveButton" runat="server" OnClick="DoSomething" />
</MyControls:Modal>

In you pages codebehind you can do:

MyPanel.Update().Show();

Fr your approach, I'd have a jQuery action that sets an input field and clicks a button in the modal, triggering the update panel to postback, and in that code that loads the details into whatever control is in the modal, just call MyPanel.Update.Show(); and it'll be on the screen when the update panel ajax request comes back.

The example above, using jQuery UI will have 2 buttons on the modal, one to close and do nothing, one to save, clicking that MySaveButton inside the modal, and you can do whatever you want on then server, calling MyPanel.Hide() if successful, or put an error message in the panel if validation fails, just don't call MyModal.Hide() and it'll stay up for the user after the postback.

Nick Craver
1) Are the controls in your detail section - ASP.NET controls? 2) Can you please explain how you implemented the save (ajax or server side call and how you do validation)?
DotnetDude
@DotnetDude - In this instance it's an update panel until I switch completely over to jqGrid, I'll update the answer with an example.
Nick Craver
@Nick - Thanks for the code snippet. I am trying to achieve this without using the UpdatePanel (which is bloated and not recommended). The Save button in the JQ modal does not fire a postback.
DotnetDude
@DotnetDude - It does if you use the code above, notice that I tell the save button to find the asp.net input element and click it `$(this).find("input[id$=MySaveButton]").click();`, **that's** what's posting back. You can easily take this example and turn it from UpdatePanel to Panel, remove the ajax calls and still get a server-side/code activated div, but you'll need something to send the script down besides ScriptManager if you're going that route.
Nick Craver