views:

321

answers:

3

Hi, I want to load some html data dynamically from the server (like a grid composed by lots f and ) using jQuery.

At the moment I load it like this:

$("#Ricerca_Div_ContenitoreRisultati table tbody").load("/Segnalazioni/CercaSegnalazioni/3");

and generate it like this:

    public ActionResult CercaSegnalazioni(int flag, string sort)
    {
        [..]

        XElement SegnalazioniTrovate = Models.Segnalazioni.Recupera(flag, sortVal);
        string ritorno = "";
        bool alterna = false;
        foreach (XElement segnalazione in SegnalazioniTrovate.Elements("dossier"))
        {
            ritorno += alterna? "<tr>" : "<tr class = \"alternata\">";
            ritorno += String.Format(@"
                <td><span style=""white-space: nowrap"">{0}</span></td>
                <td><span style=""white-space: nowrap"">{1}</span></td>
                <td style =""display : none"">{2}</td>
                <td><span style=""white-space: nowrap"">{3}</span></td>
                <td><span style=""white-space: nowrap"">{4}</span></td>
                <td><span style=""white-space: nowrap"">{5}</span></td>
            </tr>",
            (string)segnalazione.Element("NUM_DOSSIER") ?? "",
            (string)segnalazione.Element("ANAG_RAGSOC_CGN") ?? "",
            (string)segnalazione.Element("ID_RIFATT_SEGN0") ?? "",
            Tools.DecodificaStatus(int.Parse((string)segnalazione.Element("FLG_STATUS") ?? "")),
            Tools.RmuoviTime((string)segnalazione.Element("DT_ACCADIMENTO")?? ""),
            (string)segnalazione.Element("COD_RAMO_LUNA") ?? ""
            );

            alterna = !alterna;
        }
        return Content(ritorno);
    }

Or, simply put, I make up the HTML code server side with a very messy code I don't like and return it back so that it is ready to be used client-side.

Any better / cleaner solution? Thanks

+1  A: 

There's different ways of doing this, and although none of them end up looking perfectly clean, the one that works best for me is to do the HTML construction on the client side. The server can return an object that works well in javascript (let's say, List<Segnalazione>) and then the client-side handler does things like:

$(list).each(function() {
  var tr = $('<tr />').append(
    $('<td />').css('white-space', 'nowrap').text(this.NUM_DOSSIER)
  ).append(
    $('<td />').css('white-space', 'nowrap').text(this.ANAG_RAGSOC_CGN)
  )

  $("#Ricerca_Div_ContenitoreRisultati table tbody").append(tr);
});

Obviously, I'm oversimplying your output, but hopefully that gives you the idea.

If nothing else, doing it in jquery gives you the automatic escaping of values within the 'text', 'attr', and 'css' methods rather than the HttpUtility.HtmlEncode, AttributeEncode methods that would clutter up your output in C#

Clyde
Hi, thanks for the suggestion. This is something I'd like to try, but I'm working for a program on the intranet of my company. The quantity of data is like 1000, 2000 records, and the users' terminals are not that new, so transferring all that load client-side is not a good option for me, I guess.
pistacchio
I really like this technique; we use it here on Stack Overflow quite a bit! And as for the quantity of records you want to show, 1000-2000 seems excessive. Even sending down raw html from the server will result in long load times as that html is parsed/added to the DOM. I'd recommend sending down JSON in batches of 50-100 and rendering using this technique.
Jarrod Dixon
+1  A: 

The cleaner solution will be creating separate View and using more CSS:

UPDATED:

In case of Request.IsAjaxRequest() use PartialView:

Controller:

public ActionResult CercaSegnalazioni(int flag, string sort)
{
    [..]

    XElement SegnalazioniTrovate = Models.Segnalazioni.Recupera(flag, sortVal);

    return PartialView("YourPartialView", SegnalazioniTrovate);
}

YourPartialView.ascx:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<XElement>" %>

<% bool alterna = false; %>
<table id="yourTableId">
    <% foreach (XElement segnalazione in SegnalazioniTrovate.Elements("dossier")) { %>
    <tr class="<%= alterna ? "alternata" : "" %>">
    <% alterna = !alterna; %>
        <td>
            <span><%= (string)segnalazione.Element("NUM_DOSSIER") ?? "" %></span>
        </td>
        <td>
            <span><%= (string)segnalazione.Element("ANAG_RAGSOC_CGN") ?? "" %></span>
        </td>
        <td class="nodisplay">
            <%= (string)segnalazione.Element("ID_RIFATT_SEGN0") ?? "" %>
        </td>
        <td>
            <span><%= Tools.DecodificaStatus(int.Parse((string)segnalazione.Element("FLG_STATUS") ?? "")) %></span>
        </td>
        <td>
            <span><%= Tools.RmuoviTime((string)segnalazione.Element("DT_ACCADIMENTO")?? "") %></span>
        </td>
        <td>
            <span><%= (string)segnalazione.Element("COD_RAMO_LUNA") ?? "" %></span>
        </td>
    </tr>
    <% } %>
</table>

CSS:

table#yourTableId td span {
    white-space: nowrap
}

.nodisplay {
    display : none
}
eu-ge-ne
Hi,this is exactly what I had _before_ doing it in ajax. I need to emit some code to be included in an existing view, so I cannot return a complete view!
pistacchio
A: 

Your best bet is probably to de-couple the presentation from the data. This would mean avoiding having any presentation code (ie. HTML generation) in your controller.

There are 2 ways to handle this...

Nested Partial Views

Partial Views can render... other partial views. Consider something like this...

<body> Page
-- <div> Partial View "parent" (does a RenderPartial of these:)
---- <div> Partial View "child" (piece 1) </div>
---- <div> Partial View "child" (piece 2) </div>

The parent partial view simply contains RenderPartials for the children. In addition, each patial view can end up having it's own URL (/controller/parent/, /controller/child-1/, etc.). In jQuery whenever you trap an event that needs to update the UI, you can simply ajax.load the piece you need and plug it into the div.

JSON -> jQuery Render

The other way is you forgo the server creating any presentation code, and you simply have an API that returns JSON. jQuery then accepts the incoming data objects and figures out what to do with them. Depending on the complexity of what needs to be rendered on the client side, this could be easier. This has the advantage of also allowing the same server-side code to be re-used in other ways. The downside is the content won't be indexed by search engines.

T. Stone